mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 14:33:33 -07:00
debounce search
This commit is contained in:
parent
b9b0a67409
commit
2f59c72400
5 changed files with 82 additions and 40 deletions
|
@ -5,22 +5,19 @@
|
||||||
:width="modalWidth + 'px'"
|
:width="modalWidth + 'px'"
|
||||||
:content-class="top ? 'top-dialog' : undefined"
|
:content-class="top ? 'top-dialog' : undefined"
|
||||||
>
|
>
|
||||||
<v-card class="pb-10" :loading="loading" height="100%">
|
<v-card class="pb-10" height="100%">
|
||||||
<v-app-bar dark :color="color" class="mt-n1 mb-2">
|
<v-app-bar dark :color="color" class="mt-n1 mb-2">
|
||||||
<v-icon large left v-if="!loading">
|
<v-icon large left>
|
||||||
{{ titleIcon }}
|
{{ titleIcon }}
|
||||||
</v-icon>
|
</v-icon>
|
||||||
<v-progress-circular
|
|
||||||
v-else
|
|
||||||
indeterminate
|
|
||||||
color="white"
|
|
||||||
large
|
|
||||||
class="mr-2"
|
|
||||||
>
|
|
||||||
</v-progress-circular>
|
|
||||||
<v-toolbar-title class="headline"> {{ title }} </v-toolbar-title>
|
<v-toolbar-title class="headline"> {{ title }} </v-toolbar-title>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
|
<v-progress-linear
|
||||||
|
v-if="loading"
|
||||||
|
indeterminate
|
||||||
|
color="primary"
|
||||||
|
></v-progress-linear>
|
||||||
<slot> </slot>
|
<slot> </slot>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<slot name="card-actions">
|
<slot name="card-actions">
|
||||||
|
@ -33,6 +30,7 @@
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</slot>
|
</slot>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
|
|
||||||
<slot name="below-actions"> </slot>
|
<slot name="below-actions"> </slot>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
|
|
@ -221,7 +221,13 @@
|
||||||
},
|
},
|
||||||
"toolbox": {
|
"toolbox": {
|
||||||
"toolbox": "Toolbox",
|
"toolbox": "Toolbox",
|
||||||
"new-name": "New Name"
|
"new-name": "New Name",
|
||||||
|
"recipes-effected": "Recipes Effected",
|
||||||
|
"title-case-all": "Title Case All",
|
||||||
|
"no-unused-items": "No Unused Items",
|
||||||
|
"remove-unused": "Remove Unused",
|
||||||
|
"assign-all": "Assign All",
|
||||||
|
"bulk-assign": "Bulk Assign"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<template slot="card-actions">
|
<template slot="card-actions">
|
||||||
<v-btn text color="grey" @click="closeDialog">
|
<v-btn text color="grey" @click="closeDialog">
|
||||||
Cancel
|
{{ $t("general.cancel") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn
|
<v-btn
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:disabled="results.length < 1"
|
:disabled="results.length < 1"
|
||||||
>
|
>
|
||||||
Assign All
|
{{ $t("settings.toolbox.assign-all") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<template slot="below-actions">
|
<template slot="below-actions">
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
</base-dialog>
|
</base-dialog>
|
||||||
|
|
||||||
<v-btn @click="openDialog" small color="success" class="mr-1">
|
<v-btn @click="openDialog" small color="success" class="mr-1">
|
||||||
Bulk Assign
|
{{ $t("settings.toolbox.bulk-assign") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -76,6 +76,7 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
results: [],
|
||||||
search: "",
|
search: "",
|
||||||
loading: false,
|
loading: false,
|
||||||
assignTargetRecipes: [],
|
assignTargetRecipes: [],
|
||||||
|
@ -86,20 +87,25 @@ export default {
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$store.dispatch("requestAllRecipes");
|
this.$store.dispatch("requestAllRecipes");
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
search() {
|
||||||
|
this.getResults();
|
||||||
|
},
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
allRecipes() {
|
allRecipes() {
|
||||||
return this.$store.getters.getRecentRecipes;
|
return this.$store.getters.getRecentRecipes;
|
||||||
},
|
},
|
||||||
results() {
|
// results() {
|
||||||
if (this.search === null || this.search === "") {
|
// if (this.search === null || this.search === "") {
|
||||||
return [];
|
// return [];
|
||||||
}
|
// }
|
||||||
return this.allRecipes.filter(x => {
|
// return this.allRecipes.filter(x => {
|
||||||
return (
|
// return (
|
||||||
this.checkForKeywords(x.name) || this.checkForKeywords(x.description)
|
// this.checkForKeywords(x.name) || this.checkForKeywords(x.description)
|
||||||
);
|
// );
|
||||||
});
|
// });
|
||||||
},
|
// },
|
||||||
keywords() {
|
keywords() {
|
||||||
const lowered = this.search.toLowerCase();
|
const lowered = this.search.toLowerCase();
|
||||||
return lowered.split(" ");
|
return lowered.split(" ");
|
||||||
|
@ -123,6 +129,7 @@ export default {
|
||||||
await api.recipes.patch(element);
|
await api.recipes.patch(element);
|
||||||
});
|
});
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
this.closeDialog();
|
||||||
},
|
},
|
||||||
closeDialog() {
|
closeDialog() {
|
||||||
this.$refs.assignDialog.close();
|
this.$refs.assignDialog.close();
|
||||||
|
@ -131,6 +138,27 @@ export default {
|
||||||
this.$refs.assignDialog.open();
|
this.$refs.assignDialog.open();
|
||||||
this.reset();
|
this.reset();
|
||||||
},
|
},
|
||||||
|
getResults() {
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
// cancel pending call
|
||||||
|
clearTimeout(this._timerId);
|
||||||
|
this._timerId = setTimeout(() => {
|
||||||
|
this.results = this.filterResults();
|
||||||
|
}, 300);
|
||||||
|
this.loading = false;
|
||||||
|
// delay new call 500ms
|
||||||
|
},
|
||||||
|
filterResults() {
|
||||||
|
if (this.search === null || this.search === "") {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return this.allRecipes.filter(x => {
|
||||||
|
return (
|
||||||
|
this.checkForKeywords(x.name) || this.checkForKeywords(x.description)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
checkForKeywords(str) {
|
checkForKeywords(str) {
|
||||||
const searchStr = str.toLowerCase();
|
const searchStr = str.toLowerCase();
|
||||||
return this.keywords.some(x => searchStr.includes(x));
|
return this.keywords.some(x => searchStr.includes(x));
|
||||||
|
|
|
@ -4,7 +4,11 @@
|
||||||
ref="deleteDialog"
|
ref="deleteDialog"
|
||||||
title-icon="mdi-tag"
|
title-icon="mdi-tag"
|
||||||
color="error"
|
color="error"
|
||||||
:title="title"
|
:title="
|
||||||
|
$t('general.delete') +
|
||||||
|
' ' +
|
||||||
|
(isTags ? $t('recipe.tags') : $t('recipe.categories'))
|
||||||
|
"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
modal-width="400"
|
modal-width="400"
|
||||||
>
|
>
|
||||||
|
@ -16,11 +20,11 @@
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
<v-card-text v-else class=" mt-4 text-center">
|
<v-card-text v-else class=" mt-4 text-center">
|
||||||
No Unused Items
|
{{ $t("settings.toolbox.no-unused-items") }}
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<template slot="card-actions">
|
<template slot="card-actions">
|
||||||
<v-btn text color="grey" @click="closeDialog">
|
<v-btn text color="grey" @click="closeDialog">
|
||||||
Cancel
|
{{ $t("general.cancel") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn
|
<v-btn
|
||||||
|
@ -29,13 +33,13 @@
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:disabled="deleteList.length < 1"
|
:disabled="deleteList.length < 1"
|
||||||
>
|
>
|
||||||
Delete
|
{{ $t("general.delete") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
</base-dialog>
|
</base-dialog>
|
||||||
|
|
||||||
<v-btn @click="openDialog" small color="error" class="mr-1">
|
<v-btn @click="openDialog" small color="error" class="mr-1">
|
||||||
Remove Unused
|
{{ $t("settings.toolbox.remove-unused") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -58,11 +62,6 @@ export default {
|
||||||
loading: false,
|
loading: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
title() {
|
|
||||||
return this.isTags ? "Delete Tags" : "Delete Categories";
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
closeDialog() {
|
closeDialog() {
|
||||||
this.$refs.deleteDialog.close();
|
this.$refs.deleteDialog.close();
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
</v-form>
|
</v-form>
|
||||||
<template slot="below-actions">
|
<template slot="below-actions">
|
||||||
<v-card-title class="headline">
|
<v-card-title class="headline">
|
||||||
{{ renameTarget.recipes.length || 0 }} Recipes Effected
|
{{ renameTarget.recipes.length || 0 }}
|
||||||
|
{{ $t("settings.toolbox.recipes-effected") }}
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<MobileRecipeCard
|
<MobileRecipeCard
|
||||||
class="ml-2 mr-2 mt-2 mb-2"
|
class="ml-2 mr-2 mt-2 mb-2"
|
||||||
|
@ -41,12 +42,18 @@
|
||||||
class="mr-1"
|
class="mr-1"
|
||||||
>
|
>
|
||||||
<v-btn @click="openNewDialog" small color="success">
|
<v-btn @click="openNewDialog" small color="success">
|
||||||
New
|
{{ $t("general.create") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</new-category-tag-dialog>
|
</new-category-tag-dialog>
|
||||||
<BulkAssign isTags="isTags" />
|
<BulkAssign isTags="isTags" />
|
||||||
<v-btn @click="titleCaseAll" class="mr-1" small color="success">
|
<v-btn
|
||||||
Title Case All
|
@click="titleCaseAll"
|
||||||
|
class="mr-1"
|
||||||
|
small
|
||||||
|
color="success"
|
||||||
|
:loading="loadingTitleCase"
|
||||||
|
>
|
||||||
|
{{ $t("settings.toolbox.title-case-all") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<RemoveUnused :isTags="isTags" />
|
<RemoveUnused :isTags="isTags" />
|
||||||
<v-spacer> </v-spacer>
|
<v-spacer> </v-spacer>
|
||||||
|
@ -125,6 +132,7 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
loadingTitleCase: false,
|
||||||
searchString: "",
|
searchString: "",
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
renameTarget: {
|
renameTarget: {
|
||||||
|
@ -181,10 +189,11 @@ export default {
|
||||||
await api.categories.delete(name);
|
await api.categories.delete(name);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
renameFromDialog(name, newName) {
|
async renameFromDialog(name, newName) {
|
||||||
if (this.$refs.renameForm.validate()) {
|
if (this.$refs.renameForm.validate()) {
|
||||||
this.rename(name, newName);
|
await this.rename(name, newName);
|
||||||
}
|
}
|
||||||
|
this.$refs.renameDialog.close();
|
||||||
},
|
},
|
||||||
async rename(name, newName) {
|
async rename(name, newName) {
|
||||||
if (this.isTags) {
|
if (this.isTags) {
|
||||||
|
@ -197,6 +206,7 @@ export default {
|
||||||
return lowerName.replace(/(?:^|\s|-)\S/g, x => x.toUpperCase());
|
return lowerName.replace(/(?:^|\s|-)\S/g, x => x.toUpperCase());
|
||||||
},
|
},
|
||||||
async titleCaseAll() {
|
async titleCaseAll() {
|
||||||
|
this.loadingTitleCase = true;
|
||||||
const renameList = this.allItems.map(x => ({
|
const renameList = this.allItems.map(x => ({
|
||||||
slug: x.slug,
|
slug: x.slug,
|
||||||
name: x.name,
|
name: x.name,
|
||||||
|
@ -216,6 +226,7 @@ export default {
|
||||||
});
|
});
|
||||||
this.$store.dispatch("requestCategories");
|
this.$store.dispatch("requestCategories");
|
||||||
}
|
}
|
||||||
|
this.loadingTitleCase = false;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue