reload book recipes when adding filter

This commit is contained in:
smilerz
2022-02-08 12:30:11 -06:00
parent b3a830c319
commit 0e258a49fb
4 changed files with 197 additions and 208 deletions

View File

@ -650,7 +650,7 @@ class CustomFilterSerializer(SpacedModelSerializer, WritableNestedModelSerialize
class RecipeBookSerializer(SpacedModelSerializer, WritableNestedModelSerializer): class RecipeBookSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
shared = UserNameSerializer(many=True) shared = UserNameSerializer(many=True)
filter = CustomFilterSerializer(required=False) filter = CustomFilterSerializer(allow_null=True, required=False)
def create(self, validated_data): def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user validated_data['created_by'] = self.context['request'].user

View File

@ -44,7 +44,14 @@
<loading-spinner v-if="current_book === book.id && loading"></loading-spinner> <loading-spinner v-if="current_book === book.id && loading"></loading-spinner>
<transition name="slide-fade"> <transition name="slide-fade">
<cookbook-slider :recipes="recipes" :book="book" :key="`slider_${book.id}`" v-if="current_book === book.id && !loading" v-on:refresh="refreshData"></cookbook-slider> <cookbook-slider
:recipes="recipes"
:book="book"
:key="`slider_${book.id}`"
v-if="current_book === book.id && !loading"
v-on:refresh="refreshData"
@reload="openBook(current_book, true)"
></cookbook-slider>
</transition> </transition>
</div> </div>
</div> </div>
@ -95,8 +102,8 @@ export default {
this.cookbooks = result.data this.cookbooks = result.data
}) })
}, },
openBook: function (book) { openBook: function (book, keepopen = false) {
if (book === this.current_book) { if (book === this.current_book && !keepopen) {
this.current_book = undefined this.current_book = undefined
this.recipes = [] this.recipes = []
return return
@ -111,18 +118,7 @@ export default {
apiClient.listRecipeBookEntrys({ query: { book: book } }).then((result) => { apiClient.listRecipeBookEntrys({ query: { book: book } }).then((result) => {
this.recipes = result.data this.recipes = result.data
if (book_contents.filter) { if (book_contents.filter) this.appendRecipeFilter(1, book_contents)
var promises = []
var page = 1
this.appendRecipeFilter(page, book_contents).then((count) => {
while (count.total > 0) {
page++
promises.push(this.appendRecipeFilter(page, book_contents))
count.total = count.total - count.page
}
Promise.all(promises).then()
})
}
this.loading = false this.loading = false
}) })
}, },
@ -142,7 +138,7 @@ export default {
}, },
appendRecipeFilter: function (page, book) { appendRecipeFilter: function (page, book) {
let params = { page: page, options: { query: { filter: book.filter.id } } } let params = { page: page, options: { query: { filter: book.filter.id } } }
return this.genericAPI(this.Models.RECIPE, this.Actions.LIST, params).then((results) => { this.genericAPI(this.Models.RECIPE, this.Actions.LIST, params).then((results) => {
let recipes = results.data.results.map((x) => { let recipes = results.data.results.map((x) => {
return { return {
id: (Math.random() * 1999) ^ 1999, id: (Math.random() * 1999) ^ 1999,
@ -152,8 +148,11 @@ export default {
recipe_content: x, recipe_content: x,
} }
}) })
this.recipes.push(...recipes) this.recipes.push(...recipes)
return { total: results.data.count - results.data.results.length, page: results.data.results.length } if (results.data.next) {
this.appendRecipeFilter(page + 1, book)
}
}) })
}, },
}, },

View File

@ -100,6 +100,7 @@ export default {
this.editing = false this.editing = false
this.saveData() this.saveData()
this.$emit("editing", false) this.$emit("editing", false)
this.$emit("reload")
} }
}, },
updateEmoji: function (item, value) { updateEmoji: function (item, value) {
@ -109,6 +110,7 @@ export default {
}, },
saveData: function () { saveData: function () {
let apiClient = new ApiApiFactory() let apiClient = new ApiApiFactory()
console.log(this.book_copy)
apiClient apiClient
.updateRecipeBook(this.book_copy.id, this.book_copy) .updateRecipeBook(this.book_copy.id, this.book_copy)

View File

@ -1,235 +1,223 @@
<template> <template>
<div v-bind:class="{ bounceright: bounce_right, bounceleft: bounce_left }"> <div v-bind:class="{ bounceright: bounce_right, bounceleft: bounce_left }">
<div class="row"> <div class="row">
<div class="col col-md-12 text-center pt-2 pb-4"> <div class="col col-md-12 text-center pt-2 pb-4">
<b-pagination pills <b-pagination pills v-model="current_page" :total-rows="page_count_pagination" :per-page="per_page_count" @change="pageChange" first-text="📖" align="fill"> </b-pagination>
v-model="current_page" </div>
:total-rows="page_count_pagination" </div>
:per-page="per_page_count" <div class="row" v-touch:swipe.left="swipeLeft" v-touch:swipe.right="swipeRight">
@change="pageChange" <div class="col-md-1" @click="swipeRight" style="cursor: pointer"></div>
first-text="📖" <div class="col-md-5">
align="fill"> <transition name="flip" mode="out-in">
<cookbook-edit-card :book="book" v-if="current_page === 1" v-on:editing="cookbook_editing = $event" v-on:refresh="$emit('refresh')" @reload="$emit('reload')"></cookbook-edit-card>
</b-pagination> </transition>
</div> <transition name="flip" mode="out-in">
<recipe-card :recipe="display_recipes[0].recipe_content" v-if="current_page > 1" :key="display_recipes[0].recipe"></recipe-card>
</transition>
</div>
<div class="col-md-5">
<transition name="flip" mode="out-in">
<cookbook-toc :recipes="recipes" v-if="current_page === 1" v-on:switchRecipe="switchRecipe($event)"></cookbook-toc>
</transition>
<transition name="flip" mode="out-in">
<recipe-card :recipe="display_recipes[1].recipe_content" v-if="current_page > 1 && display_recipes.length === 2" :key="display_recipes[1].recipe"></recipe-card>
</transition>
</div>
<div class="col-md-1" @click="swipeLeft" style="cursor: pointer"></div>
</div>
</div> </div>
<div class="row" v-touch:swipe.left="swipeLeft" v-touch:swipe.right="swipeRight">
<div class="col-md-1" @click="swipeRight" style="cursor: pointer;">
</div>
<div class="col-md-5">
<transition name="flip" mode="out-in">
<cookbook-edit-card :book="book" v-if="current_page === 1"
v-on:editing="cookbook_editing = $event"
v-on:refresh="$emit('refresh')"></cookbook-edit-card>
</transition>
<transition name="flip" mode="out-in">
<recipe-card :recipe="display_recipes[0].recipe_content"
v-if="current_page > 1" :key="display_recipes[0].recipe"></recipe-card>
</transition>
</div>
<div class="col-md-5">
<transition name="flip" mode="out-in">
<cookbook-toc :recipes="recipes" v-if="current_page === 1"
v-on:switchRecipe="switchRecipe($event)"></cookbook-toc>
</transition>
<transition name="flip" mode="out-in">
<recipe-card :recipe="display_recipes[1].recipe_content"
v-if="current_page > 1 && display_recipes.length === 2"
:key="display_recipes[1].recipe"></recipe-card>
</transition>
</div>
<div class="col-md-1" @click="swipeLeft" style="cursor: pointer;">
</div>
</div>
</div>
</template> </template>
<script> <script>
import RecipeCard from "./RecipeCard"
import RecipeCard from "./RecipeCard"; import CookbookEditCard from "./CookbookEditCard"
import CookbookEditCard from "./CookbookEditCard"; import CookbookToc from "./CookbookToc"
import CookbookToc from "./CookbookToc";
import Vue2TouchEvents from "vue2-touch-events" import Vue2TouchEvents from "vue2-touch-events"
import Vue from "vue"; import Vue from "vue"
import {ApiApiFactory} from "../utils/openapi/api"; import { ApiApiFactory } from "../utils/openapi/api"
Vue.use(Vue2TouchEvents) Vue.use(Vue2TouchEvents)
export default { export default {
name: "CookbookSlider.vue", name: "CookbookSlider.vue",
components: {CookbookToc, CookbookEditCard, RecipeCard}, components: { CookbookToc, CookbookEditCard, RecipeCard },
props: { props: {
recipes: Array, recipes: Array,
book: Object book: Object,
},
computed: {
page_count_pagination: function () {
return this.recipes.length + 2
}, },
page_count: function () { computed: {
return Math.ceil(this.page_count_pagination / this.per_page_count) page_count_pagination: function () {
} return this.recipes.length + 2
}, },
data() { page_count: function () {
return { return Math.ceil(this.page_count_pagination / this.per_page_count)
display_recipes: [], },
current_page: 1,
per_page_count: 2,
bounce_left: false,
bounce_right: false,
cookbook_editing: false
}
},
methods: {
pageChange: function (page) {
this.current_page = page
this.display_recipes = this.recipes.slice(((this.current_page - 1) - 1) * 2, (this.current_page - 1) * 2)
this.loadRecipeDetails(page)
}, },
loadRecipeDetails: function (page) { data() {
this.display_recipes.forEach((recipe, index) => { return {
let apiClient = new ApiApiFactory() display_recipes: [],
current_page: 1,
per_page_count: 2,
bounce_left: false,
bounce_right: false,
cookbook_editing: false,
}
},
methods: {
pageChange: function (page) {
this.current_page = page
this.display_recipes = this.recipes.slice((this.current_page - 1 - 1) * 2, (this.current_page - 1) * 2)
this.loadRecipeDetails(page)
},
loadRecipeDetails: function (page) {
this.display_recipes.forEach((recipe, index) => {
let apiClient = new ApiApiFactory()
apiClient.retrieveRecipe(recipe.recipe).then(result => { apiClient.retrieveRecipe(recipe.recipe).then((result) => {
let new_entry = Object.assign({}, recipe); let new_entry = Object.assign({}, recipe)
new_entry.recipe_content = result.data new_entry.recipe_content = result.data
this.$set(this.display_recipes, index, new_entry) this.$set(this.display_recipes, index, new_entry)
}) })
}) })
},
swipeLeft: function () {
if (this.cookbook_editing) {
return
}
if (this.current_page < this.page_count) {
this.pageChange(this.current_page + 1)
} else {
this.bounce_left = true
setTimeout(() => (this.bounce_left = false), 500)
}
},
swipeRight: function () {
if (this.cookbook_editing) {
return
}
if (this.current_page > 1) {
this.pageChange(this.current_page - 1)
} else {
this.bounce_right = true
setTimeout(() => (this.bounce_right = false), 500)
}
},
switchRecipe: function (index) {
this.pageChange(Math.ceil((index + 1) / this.per_page_count) + 1)
},
}, },
swipeLeft: function () { directives: {
if (this.cookbook_editing) { hover: {
return inserted: function (el) {
} el.addEventListener("mouseenter", () => {
if (this.current_page < this.page_count) { el.classList.add("shadow")
this.pageChange(this.current_page + 1) })
} else { el.addEventListener("mouseleave", () => {
this.bounce_left = true el.classList.remove("shadow")
setTimeout(() => this.bounce_left = false, 500); })
} },
},
}, },
swipeRight: function () {
if (this.cookbook_editing) {
return
}
if (this.current_page > 1) {
this.pageChange(this.current_page - 1)
} else {
this.bounce_right = true
setTimeout(() => this.bounce_right = false, 500);
}
},
switchRecipe: function (index) {
this.pageChange(Math.ceil((index + 1) / this.per_page_count) + 1)
}
},
directives: {
hover: {
inserted: function (el) {
el.addEventListener('mouseenter', () => {
el.classList.add("shadow")
});
el.addEventListener('mouseleave', () => {
el.classList.remove("shadow")
});
}
}
}
} }
</script> </script>
<style scoped> <style scoped>
.flip-enter-active { .flip-enter-active {
-webkit-animation-name: bounceUp; -webkit-animation-name: bounceUp;
animation-name: bounceUp; animation-name: bounceUp;
-webkit-animation-duration: .5s; -webkit-animation-duration: 0.5s;
animation-duration: .5s; animation-duration: 0.5s;
-webkit-animation-fill-mode: both; -webkit-animation-fill-mode: both;
animation-fill-mode: both; animation-fill-mode: both;
-webkit-animation-timing-function: linear; -webkit-animation-timing-function: linear;
animation-timing-function: linear; animation-timing-function: linear;
animation-iteration-count: infinite; animation-iteration-count: infinite;
-webkit-animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite;
} }
.bounceleft { .bounceleft {
-webkit-animation-name: bounceLeft; -webkit-animation-name: bounceLeft;
animation-name: bounceLeft; animation-name: bounceLeft;
-webkit-animation-duration: .5s; -webkit-animation-duration: 0.5s;
animation-duration: .5s; animation-duration: 0.5s;
-webkit-animation-fill-mode: both; -webkit-animation-fill-mode: both;
animation-fill-mode: both; animation-fill-mode: both;
-webkit-animation-timing-function: linear; -webkit-animation-timing-function: linear;
animation-timing-function: linear; animation-timing-function: linear;
animation-iteration-count: 1; animation-iteration-count: 1;
-webkit-animation-iteration-count: 1; -webkit-animation-iteration-count: 1;
} }
.bounceright { .bounceright {
-webkit-animation-name: bounceRight; -webkit-animation-name: bounceRight;
animation-name: bounceRight; animation-name: bounceRight;
-webkit-animation-duration: .5s; -webkit-animation-duration: 0.5s;
animation-duration: .5s; animation-duration: 0.5s;
-webkit-animation-fill-mode: both; -webkit-animation-fill-mode: both;
animation-fill-mode: both; animation-fill-mode: both;
-webkit-animation-timing-function: linear; -webkit-animation-timing-function: linear;
animation-timing-function: linear; animation-timing-function: linear;
animation-iteration-count: 1; animation-iteration-count: 1;
-webkit-animation-iteration-count: 1; -webkit-animation-iteration-count: 1;
} }
@-webkit-keyframes bounceUp { @-webkit-keyframes bounceUp {
0%, 100% { 0%,
-webkit-transform: translateY(0); 100% {
} -webkit-transform: translateY(0);
50% { }
-webkit-transform: translateY(-7px); 50% {
} -webkit-transform: translateY(-7px);
}
} }
@keyframes bounceUp { @keyframes bounceUp {
0%, 100% { 0%,
transform: translateY(0); 100% {
} transform: translateY(0);
50% { }
transform: translateY(-7px); 50% {
} transform: translateY(-7px);
}
} }
@-webkit-keyframes bounceLeft { @-webkit-keyframes bounceLeft {
0%, 100% { 0%,
-webkit-transform: translateY(0); 100% {
} -webkit-transform: translateY(0);
50% { }
-webkit-transform: translateX(-10px); 50% {
} -webkit-transform: translateX(-10px);
}
} }
@keyframes bounceLeft { @keyframes bounceLeft {
0%, 100% { 0%,
transform: translateY(0); 100% {
} transform: translateY(0);
50% { }
transform: translateX(-10px); 50% {
} transform: translateX(-10px);
}
} }
@-webkit-keyframes bounceRight { @-webkit-keyframes bounceRight {
0%, 100% { 0%,
-webkit-transform: translateY(0); 100% {
} -webkit-transform: translateY(0);
50% { }
-webkit-transform: translateX(10px); 50% {
} -webkit-transform: translateX(10px);
}
} }
@keyframes bounceRight { @keyframes bounceRight {
0%, 100% { 0%,
transform: translateY(0); 100% {
} transform: translateY(0);
50% { }
transform: translateX(10px); 50% {
} transform: translateX(10px);
}
} }
</style> </style>