Merge pull request #1088 from smilerz/search_troubleshooting
add search debug
This commit is contained in:
commit
7c985cec23
1
.gitignore
vendored
1
.gitignore
vendored
@ -84,3 +84,4 @@ vetur.config.js
|
||||
cookbook/static/vue
|
||||
vue/webpack-stats.json
|
||||
cookbook/templates/sw.js
|
||||
.prettierignore
|
||||
|
@ -1,17 +1,17 @@
|
||||
from collections import Counter
|
||||
from datetime import timedelta
|
||||
|
||||
from recipes import settings
|
||||
from django.contrib.postgres.search import (
|
||||
SearchQuery, SearchRank, TrigramSimilarity
|
||||
)
|
||||
from django.contrib.postgres.search import SearchQuery, SearchRank, TrigramSimilarity
|
||||
from django.core.cache import caches
|
||||
from django.db.models import Avg, Case, Count, Func, Max, Q, Subquery, Value, When
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.utils import timezone, translation
|
||||
|
||||
from cookbook.filters import RecipeFilter
|
||||
from cookbook.helper.permission_helper import has_group_permission
|
||||
from cookbook.managers import DICTIONARY
|
||||
from cookbook.models import Food, Keyword, ViewLog, SearchPreference
|
||||
from cookbook.models import Food, Keyword, Recipe, SearchPreference, ViewLog
|
||||
from recipes import settings
|
||||
|
||||
|
||||
class Round(Func):
|
||||
@ -400,3 +400,13 @@ def annotated_qs(qs, root=False, fill=False):
|
||||
if start_depth and start_depth > 0:
|
||||
info['close'] = list(range(0, prev_depth - start_depth + 1))
|
||||
return result
|
||||
|
||||
|
||||
def old_search(request):
|
||||
if has_group_permission(request.user, ('guest',)):
|
||||
params = dict(request.GET)
|
||||
params['internal'] = None
|
||||
f = RecipeFilter(params,
|
||||
queryset=Recipe.objects.filter(space=request.user.userpreference.space).all().order_by('name'),
|
||||
space=request.space)
|
||||
return f.qs
|
||||
|
@ -345,6 +345,7 @@
|
||||
localStorage.setItem('SCRIPT_NAME', "{% base_path request 'script' %}")
|
||||
localStorage.setItem('BASE_PATH', "{% base_path request 'base' %}")
|
||||
localStorage.setItem('STATIC_URL', "{% base_path request 'static_base' %}")
|
||||
localStorage.setItem('DEBUG', "{% is_debug %}")
|
||||
window.addEventListener("load", () => {
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.register("{% url 'service_worker' %}", {scope: "{% base_path request 'base' %}" + '/'}).then(function (reg) {
|
||||
|
@ -2,17 +2,17 @@ from pydoc import locate
|
||||
|
||||
from django.urls import include, path
|
||||
from django.views.generic import TemplateView
|
||||
from recipes.version import VERSION_NUMBER
|
||||
from rest_framework import routers, permissions
|
||||
from rest_framework import permissions, routers
|
||||
from rest_framework.schemas import get_schema_view
|
||||
|
||||
from cookbook.helper import dal
|
||||
from recipes.settings import DEBUG
|
||||
from recipes.version import VERSION_NUMBER
|
||||
|
||||
from .models import (Comment, Food, InviteLink, Keyword, MealPlan, Recipe,
|
||||
RecipeBook, RecipeBookEntry, RecipeImport, ShoppingList,
|
||||
Storage, Supermarket, SupermarketCategory, Sync, SyncLog, Unit, get_model_name, Automation,
|
||||
UserFile, Step)
|
||||
from .views import api, data, delete, edit, import_export, lists, new, views, telegram
|
||||
from .models import (Automation, Comment, Food, InviteLink, Keyword, MealPlan, Recipe, RecipeBook,
|
||||
RecipeBookEntry, RecipeImport, ShoppingList, Step, Storage, Supermarket,
|
||||
SupermarketCategory, Sync, SyncLog, Unit, UserFile, get_model_name)
|
||||
from .views import api, data, delete, edit, import_export, lists, new, telegram, views
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'user-name', api.UserNameViewSet, basename='username')
|
||||
@ -68,8 +68,6 @@ urlpatterns = [
|
||||
path('history/', views.history, name='view_history'),
|
||||
path('supermarket/', views.supermarket, name='view_supermarket'),
|
||||
path('abuse/<slug:token>', views.report_share_abuse, name='view_report_share_abuse'),
|
||||
path('test/', views.test, name='view_test'),
|
||||
path('test2/', views.test2, name='view_test2'),
|
||||
|
||||
path('import/', import_export.import_recipe, name='view_import'),
|
||||
path('import-response/<int:pk>/', import_export.import_response, name='view_import_response'),
|
||||
@ -189,3 +187,7 @@ for m in vue_models:
|
||||
f'list/{url_name}/', c, name=f'list_{py_name}'
|
||||
)
|
||||
)
|
||||
|
||||
if DEBUG:
|
||||
urlpatterns.append(path('test/', views.test, name='view_test'))
|
||||
urlpatterns.append(path('test2/', views.test2, name='view_test2'))
|
||||
|
@ -2,11 +2,11 @@ import io
|
||||
import json
|
||||
import re
|
||||
import uuid
|
||||
from collections import OrderedDict
|
||||
|
||||
import requests
|
||||
from annoying.decorators import ajax_request
|
||||
from annoying.functions import get_object_or_None
|
||||
from collections import OrderedDict
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.postgres.search import TrigramSimilarity
|
||||
@ -15,12 +15,12 @@ from django.core.files import File
|
||||
from django.db.models import Case, ProtectedError, Q, Value, When
|
||||
from django.db.models.fields.related import ForeignObjectRel
|
||||
from django.http import FileResponse, HttpResponse, JsonResponse
|
||||
from django_scopes import scopes_disabled
|
||||
from django.shortcuts import redirect, get_object_or_404
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django_scopes import scopes_disabled
|
||||
from icalendar import Calendar, Event
|
||||
from recipe_scrapers import scrape_me, WebsiteNotImplementedError, NoSchemaFoundInWildMode
|
||||
from recipe_scrapers import NoSchemaFoundInWildMode, WebsiteNotImplementedError, scrape_me
|
||||
from rest_framework import decorators, status, viewsets
|
||||
from rest_framework.exceptions import APIException, PermissionDenied
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
@ -28,41 +28,39 @@ from rest_framework.parsers import MultiPartParser
|
||||
from rest_framework.renderers import JSONRenderer, TemplateHTMLRenderer
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ViewSetMixin
|
||||
from treebeard.exceptions import PathOverflow, InvalidMoveToDescendant, InvalidPosition
|
||||
from treebeard.exceptions import InvalidMoveToDescendant, InvalidPosition, PathOverflow
|
||||
|
||||
from cookbook.helper.image_processing import handle_image
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest,
|
||||
CustomIsOwner, CustomIsShare,
|
||||
CustomIsShared, CustomIsUser,
|
||||
from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, CustomIsOwner,
|
||||
CustomIsShare, CustomIsShared, CustomIsUser,
|
||||
group_required)
|
||||
from cookbook.helper.recipe_html_import import get_recipe_from_source
|
||||
|
||||
from cookbook.helper.recipe_search import search_recipes, get_facet
|
||||
from cookbook.helper.recipe_search import get_facet, old_search, search_recipes
|
||||
from cookbook.helper.recipe_url_import import get_from_scraper
|
||||
from cookbook.models import (CookLog, Food, Ingredient, Keyword, MealPlan,
|
||||
MealType, Recipe, RecipeBook, ShoppingList,
|
||||
ShoppingListEntry, ShoppingListRecipe, Step,
|
||||
Storage, Sync, SyncLog, Unit, UserPreference,
|
||||
ViewLog, RecipeBookEntry, Supermarket, ImportLog, BookmarkletImport, SupermarketCategory, UserFile, ShareLink, SupermarketCategoryRelation, Automation)
|
||||
from cookbook.models import (Automation, BookmarkletImport, CookLog, Food, ImportLog, Ingredient,
|
||||
Keyword, MealPlan, MealType, Recipe, RecipeBook, RecipeBookEntry,
|
||||
ShareLink, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Step,
|
||||
Storage, Supermarket, SupermarketCategory, SupermarketCategoryRelation,
|
||||
Sync, SyncLog, Unit, UserFile, UserPreference, ViewLog)
|
||||
from cookbook.provider.dropbox import Dropbox
|
||||
from cookbook.provider.local import Local
|
||||
from cookbook.provider.nextcloud import Nextcloud
|
||||
from cookbook.schemas import FilterSchema, RecipeSchema, TreeSchema, QueryOnlySchema
|
||||
from cookbook.serializer import (FoodSerializer, IngredientSerializer,
|
||||
KeywordSerializer, MealPlanSerializer,
|
||||
MealTypeSerializer, RecipeBookSerializer,
|
||||
RecipeImageSerializer, RecipeSerializer,
|
||||
ShoppingListAutoSyncSerializer,
|
||||
ShoppingListEntrySerializer,
|
||||
ShoppingListRecipeSerializer,
|
||||
ShoppingListSerializer, StepSerializer,
|
||||
StorageSerializer, SyncLogSerializer,
|
||||
SyncSerializer, UnitSerializer,
|
||||
UserNameSerializer, UserPreferenceSerializer,
|
||||
ViewLogSerializer, CookLogSerializer, RecipeBookEntrySerializer,
|
||||
RecipeOverviewSerializer, SupermarketSerializer, ImportLogSerializer,
|
||||
BookmarkletImportSerializer, SupermarketCategorySerializer, UserFileSerializer, SupermarketCategoryRelationSerializer, AutomationSerializer)
|
||||
from cookbook.schemas import FilterSchema, QueryOnlySchema, RecipeSchema, TreeSchema
|
||||
from cookbook.serializer import (AutomationSerializer, BookmarkletImportSerializer,
|
||||
CookLogSerializer, FoodSerializer, ImportLogSerializer,
|
||||
IngredientSerializer, KeywordSerializer, MealPlanSerializer,
|
||||
MealTypeSerializer, RecipeBookEntrySerializer,
|
||||
RecipeBookSerializer, RecipeImageSerializer,
|
||||
RecipeOverviewSerializer, RecipeSerializer,
|
||||
ShoppingListAutoSyncSerializer, ShoppingListEntrySerializer,
|
||||
ShoppingListRecipeSerializer, ShoppingListSerializer,
|
||||
StepSerializer, StorageSerializer,
|
||||
SupermarketCategoryRelationSerializer,
|
||||
SupermarketCategorySerializer, SupermarketSerializer,
|
||||
SyncLogSerializer, SyncSerializer, UnitSerializer,
|
||||
UserFileSerializer, UserNameSerializer, UserPreferenceSerializer,
|
||||
ViewLogSerializer)
|
||||
from recipes import settings
|
||||
|
||||
|
||||
@ -547,7 +545,16 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
||||
|
||||
return super().get_queryset()
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
if self.request.GET.get('debug', False):
|
||||
return JsonResponse({
|
||||
'new': str(self.get_queryset().query),
|
||||
'old': str(old_search(request).query)
|
||||
})
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
# TODO write extensive tests for permissions
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'list':
|
||||
return RecipeOverviewSerializer
|
||||
|
@ -13,7 +13,7 @@ from django.contrib.auth.password_validation import validate_password
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.models import Avg, Q, Sum
|
||||
from django.http import HttpResponseRedirect, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, render, redirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext as _
|
||||
@ -22,16 +22,15 @@ from django_tables2 import RequestConfig
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
from cookbook.filters import RecipeFilter
|
||||
from cookbook.forms import (CommentForm, Recipe, User,
|
||||
UserCreateForm, UserNameForm, UserPreference,
|
||||
UserPreferenceForm, SpaceJoinForm, SpaceCreateForm,
|
||||
SearchPreferenceForm)
|
||||
from cookbook.helper.permission_helper import group_required, share_link_valid, has_group_permission
|
||||
from cookbook.models import (Comment, CookLog, InviteLink, MealPlan,
|
||||
ViewLog, ShoppingList, Space, Keyword, RecipeImport, Unit,
|
||||
Food, UserFile, ShareLink, SearchPreference, SearchFields)
|
||||
from cookbook.tables import (CookLogTable, RecipeTable, RecipeTableSmall,
|
||||
ViewLogTable, InviteLinkTable)
|
||||
from cookbook.forms import (CommentForm, Recipe, SearchPreferenceForm, SpaceCreateForm,
|
||||
SpaceJoinForm, User, UserCreateForm, UserNameForm, UserPreference,
|
||||
UserPreferenceForm)
|
||||
from cookbook.helper.permission_helper import group_required, has_group_permission, share_link_valid
|
||||
from cookbook.models import (Comment, CookLog, Food, InviteLink, Keyword, MealPlan, RecipeImport,
|
||||
SearchFields, SearchPreference, ShareLink, ShoppingList, Space, Unit,
|
||||
UserFile, ViewLog)
|
||||
from cookbook.tables import (CookLogTable, InviteLinkTable, RecipeTable, RecipeTableSmall,
|
||||
ViewLogTable)
|
||||
from cookbook.views.data import Object
|
||||
from recipes.version import BUILD_REF, VERSION_NUMBER
|
||||
|
||||
@ -382,7 +381,7 @@ def user_settings(request):
|
||||
if up:
|
||||
preference_form = UserPreferenceForm(instance=up, space=request.space)
|
||||
else:
|
||||
preference_form = UserPreferenceForm( space=request.space)
|
||||
preference_form = UserPreferenceForm(space=request.space)
|
||||
|
||||
fields_searched = len(sp.icontains.all()) + len(sp.istartswith.all()) + len(sp.trigram.all()) + len(
|
||||
sp.fulltext.all())
|
||||
|
@ -7,140 +7,100 @@
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-10 col-xl-8 mt-3 mb-3">
|
||||
<b-input-group>
|
||||
<b-input class="form-control form-control-lg form-control-borderless form-control-search" v-model="settings.search_input"
|
||||
v-bind:placeholder="$t('Search')"></b-input>
|
||||
<b-input
|
||||
class="form-control form-control-lg form-control-borderless form-control-search"
|
||||
v-model="settings.search_input"
|
||||
v-bind:placeholder="$t('Search')"
|
||||
></b-input>
|
||||
<b-input-group-append>
|
||||
<b-button variant="light"
|
||||
v-b-tooltip.hover :title="$t('Random Recipes')"
|
||||
@click="openRandom()">
|
||||
<b-button v-b-tooltip.hover :title="$t('show_sql')" @click="showSQL()">
|
||||
<i class="fas fa-bug" style="font-size: 1.5em"></i>
|
||||
</b-button>
|
||||
<b-button variant="light" v-b-tooltip.hover :title="$t('Random Recipes')" @click="openRandom()">
|
||||
<i class="fas fa-dice-five" style="font-size: 1.5em"></i>
|
||||
</b-button>
|
||||
<b-button v-b-toggle.collapse_advanced_search
|
||||
v-b-tooltip.hover :title="$t('Advanced Settings')"
|
||||
<b-button
|
||||
v-b-toggle.collapse_advanced_search
|
||||
v-b-tooltip.hover
|
||||
:title="$t('Advanced Settings')"
|
||||
v-bind:variant="!isAdvancedSettingsSet() ? 'primary' : 'danger'"
|
||||
>
|
||||
<!-- TODO consider changing this icon to a filter -->
|
||||
<i class="fas fa-caret-down" v-if="!settings.advanced_search_visible"></i>
|
||||
<i class="fas fa-caret-up" v-if="settings.advanced_search_visible"></i>
|
||||
</b-button>
|
||||
|
||||
</b-input-group-append>
|
||||
</b-input-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<b-collapse id="collapse_advanced_search" class="mt-2 shadow-sm" v-model="settings.advanced_search_visible">
|
||||
<div class="card">
|
||||
<div class="card-body p-4">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<a class="btn btn-primary btn-block text-uppercase"
|
||||
:href="resolveDjangoUrl('new_recipe')">{{ $t('New_Recipe') }}</a>
|
||||
<a class="btn btn-primary btn-block text-uppercase" :href="resolveDjangoUrl('new_recipe')">{{ $t("New_Recipe") }}</a>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<a class="btn btn-primary btn-block text-uppercase"
|
||||
:href="resolveDjangoUrl('data_import_url')">{{ $t('Import') }}</a>
|
||||
<a class="btn btn-primary btn-block text-uppercase" :href="resolveDjangoUrl('data_import_url')">{{ $t("Import") }}</a>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<button class="btn btn-block text-uppercase" v-b-tooltip.hover :title="$t('show_only_internal')"
|
||||
v-bind:class="{'btn-success':settings.search_internal, 'btn-primary':!settings.search_internal}"
|
||||
@click="settings.search_internal = !settings.search_internal;refreshData()">
|
||||
{{ $t('Internal') }}
|
||||
<button
|
||||
class="btn btn-block text-uppercase"
|
||||
v-b-tooltip.hover
|
||||
:title="$t('show_only_internal')"
|
||||
v-bind:class="{ 'btn-success': settings.search_internal, 'btn-primary': !settings.search_internal }"
|
||||
@click="
|
||||
settings.search_internal = !settings.search_internal
|
||||
refreshData()
|
||||
"
|
||||
>
|
||||
{{ $t("Internal") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<button id="id_settings_button" class="btn btn-primary btn-block text-uppercase"><i
|
||||
class="fas fa-cog fa-lg m-1"></i>
|
||||
</button>
|
||||
<button id="id_settings_button" class="btn btn-primary btn-block text-uppercase"><i class="fas fa-cog fa-lg m-1"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<b-popover
|
||||
target="id_settings_button"
|
||||
triggers="click"
|
||||
placement="bottom"
|
||||
:title="$t('Settings')">
|
||||
<b-popover target="id_settings_button" triggers="click" placement="bottom" :title="$t('Settings')">
|
||||
<div>
|
||||
<b-form-group
|
||||
v-bind:label="$t('Recently_Viewed')"
|
||||
label-for="popover-input-1"
|
||||
label-cols="6"
|
||||
class="mb-3">
|
||||
<b-form-input
|
||||
type="number"
|
||||
v-model="settings.recently_viewed"
|
||||
id="popover-input-1"
|
||||
size="sm"
|
||||
></b-form-input>
|
||||
<b-form-group v-bind:label="$t('Recently_Viewed')" label-for="popover-input-1" label-cols="6" class="mb-3">
|
||||
<b-form-input type="number" v-model="settings.recently_viewed" id="popover-input-1" size="sm"></b-form-input>
|
||||
</b-form-group>
|
||||
|
||||
<b-form-group v-bind:label="$t('Recipes_per_page')" label-for="popover-input-page-count" label-cols="6" class="mb-3">
|
||||
<b-form-input type="number" v-model="settings.page_count" id="popover-input-page-count" size="sm"></b-form-input>
|
||||
</b-form-group>
|
||||
|
||||
<b-form-group v-bind:label="$t('Meal_Plan')" label-for="popover-input-2" label-cols="6" class="mb-3">
|
||||
<b-form-checkbox switch v-model="settings.show_meal_plan" id="popover-input-2" size="sm"></b-form-checkbox>
|
||||
</b-form-group>
|
||||
|
||||
<b-form-group
|
||||
v-bind:label="$t('Recipes_per_page')"
|
||||
label-for="popover-input-page-count"
|
||||
label-cols="6"
|
||||
class="mb-3">
|
||||
<b-form-input
|
||||
type="number"
|
||||
v-model="settings.page_count"
|
||||
id="popover-input-page-count"
|
||||
size="sm"
|
||||
></b-form-input>
|
||||
</b-form-group>
|
||||
|
||||
<b-form-group
|
||||
v-bind:label="$t('Meal_Plan')"
|
||||
label-for="popover-input-2"
|
||||
label-cols="6"
|
||||
class="mb-3">
|
||||
<b-form-checkbox
|
||||
switch
|
||||
v-model="settings.show_meal_plan"
|
||||
id="popover-input-2"
|
||||
size="sm"
|
||||
></b-form-checkbox>
|
||||
</b-form-group>
|
||||
|
||||
<b-form-group v-if="settings.show_meal_plan"
|
||||
v-if="settings.show_meal_plan"
|
||||
v-bind:label="$t('Meal_Plan_Days')"
|
||||
label-for="popover-input-5"
|
||||
label-cols="6"
|
||||
class="mb-3">
|
||||
<b-form-input
|
||||
type="number"
|
||||
v-model="settings.meal_plan_days"
|
||||
id="popover-input-5"
|
||||
size="sm"
|
||||
></b-form-input>
|
||||
class="mb-3"
|
||||
>
|
||||
<b-form-input type="number" v-model="settings.meal_plan_days" id="popover-input-5" size="sm"></b-form-input>
|
||||
</b-form-group>
|
||||
|
||||
<b-form-group
|
||||
v-bind:label="$t('Sort_by_new')"
|
||||
label-for="popover-input-3"
|
||||
label-cols="6"
|
||||
class="mb-3">
|
||||
<b-form-checkbox
|
||||
switch
|
||||
v-model="settings.sort_by_new"
|
||||
id="popover-input-3"
|
||||
size="sm"
|
||||
></b-form-checkbox>
|
||||
<b-form-group v-bind:label="$t('Sort_by_new')" label-for="popover-input-3" label-cols="6" class="mb-3">
|
||||
<b-form-checkbox switch v-model="settings.sort_by_new" id="popover-input-3" size="sm"></b-form-checkbox>
|
||||
</b-form-group>
|
||||
</div>
|
||||
<div class="row" style="margin-top: 1vh">
|
||||
<div class="col-12">
|
||||
<a :href="resolveDjangoUrl('view_settings') + '#search'">{{ $t('Advanced Search Settings') }}</a>
|
||||
<a :href="resolveDjangoUrl('view_settings') + '#search'">{{ $t("Advanced Search Settings") }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="margin-top: 1vh">
|
||||
<div class="col-12" style="text-align: right">
|
||||
<b-button size="sm" variant="secondary" style="margin-right:8px"
|
||||
@click="$root.$emit('bv::hide::popover')">{{ $t('Close') }}
|
||||
<b-button size="sm" variant="secondary" style="margin-right: 8px" @click="$root.$emit('bv::hide::popover')"
|
||||
>{{ $t("Close") }}
|
||||
</b-button>
|
||||
</div>
|
||||
</div>
|
||||
@ -150,17 +110,28 @@
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<b-input-group class="mt-2">
|
||||
<treeselect v-model="settings.search_keywords" :options="facets.Keywords" :flat="true"
|
||||
searchNested multiple :placeholder="$t('Keywords')" :normalizer="normalizer"
|
||||
<treeselect
|
||||
v-model="settings.search_keywords"
|
||||
:options="facets.Keywords"
|
||||
:flat="true"
|
||||
searchNested
|
||||
multiple
|
||||
:placeholder="$t('Keywords')"
|
||||
:normalizer="normalizer"
|
||||
@input="refreshData(false)"
|
||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"/>
|
||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||
/>
|
||||
<b-input-group-append>
|
||||
<b-input-group-text>
|
||||
<b-form-checkbox v-model="settings.search_keywords_or" name="check-button"
|
||||
<b-form-checkbox
|
||||
v-model="settings.search_keywords_or"
|
||||
name="check-button"
|
||||
@change="refreshData(false)"
|
||||
class="shadow-none" switch>
|
||||
<span class="text-uppercase" v-if="settings.search_keywords_or">{{ $t('or') }}</span>
|
||||
<span class="text-uppercase" v-else>{{ $t('and') }}</span>
|
||||
class="shadow-none"
|
||||
switch
|
||||
>
|
||||
<span class="text-uppercase" v-if="settings.search_keywords_or">{{ $t("or") }}</span>
|
||||
<span class="text-uppercase" v-else>{{ $t("and") }}</span>
|
||||
</b-form-checkbox>
|
||||
</b-input-group-text>
|
||||
</b-input-group-append>
|
||||
@ -172,17 +143,28 @@
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<b-input-group class="mt-2">
|
||||
<treeselect v-model="settings.search_foods" :options="facets.Foods" :flat="true"
|
||||
searchNested multiple :placeholder="$t('Ingredients')" :normalizer="normalizer"
|
||||
<treeselect
|
||||
v-model="settings.search_foods"
|
||||
:options="facets.Foods"
|
||||
:flat="true"
|
||||
searchNested
|
||||
multiple
|
||||
:placeholder="$t('Ingredients')"
|
||||
:normalizer="normalizer"
|
||||
@input="refreshData(false)"
|
||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"/>
|
||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||
/>
|
||||
<b-input-group-append>
|
||||
<b-input-group-text>
|
||||
<b-form-checkbox v-model="settings.search_foods_or" name="check-button"
|
||||
<b-form-checkbox
|
||||
v-model="settings.search_foods_or"
|
||||
name="check-button"
|
||||
@change="refreshData(false)"
|
||||
class="shadow-none" switch>
|
||||
<span class="text-uppercase" v-if="settings.search_foods_or">{{ $t('or') }}</span>
|
||||
<span class="text-uppercase" v-else>{{ $t('and') }}</span>
|
||||
class="shadow-none"
|
||||
switch
|
||||
>
|
||||
<span class="text-uppercase" v-if="settings.search_foods_or">{{ $t("or") }}</span>
|
||||
<span class="text-uppercase" v-else>{{ $t("and") }}</span>
|
||||
</b-form-checkbox>
|
||||
</b-input-group-text>
|
||||
</b-input-group-append>
|
||||
@ -194,18 +176,27 @@
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<b-input-group class="mt-2">
|
||||
<generic-multiselect @change="genericSelectChanged" parent_variable="search_books"
|
||||
<generic-multiselect
|
||||
@change="genericSelectChanged"
|
||||
parent_variable="search_books"
|
||||
:initial_selection="settings.search_books"
|
||||
:model="Models.RECIPE_BOOK"
|
||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||
v-bind:placeholder="$t('Books')" :limit="50"></generic-multiselect>
|
||||
v-bind:placeholder="$t('Books')"
|
||||
:limit="50"
|
||||
></generic-multiselect>
|
||||
<b-input-group-append>
|
||||
<b-input-group-text>
|
||||
<b-form-checkbox v-model="settings.search_books_or" name="check-button"
|
||||
<b-form-checkbox
|
||||
v-model="settings.search_books_or"
|
||||
name="check-button"
|
||||
@change="refreshData(false)"
|
||||
class="shadow-none" tyle="width: 100%" switch>
|
||||
<span class="text-uppercase" v-if="settings.search_books_or">{{ $t('or') }}</span>
|
||||
<span class="text-uppercase" v-else>{{ $t('and') }}</span>
|
||||
class="shadow-none"
|
||||
tyle="width: 100%"
|
||||
switch
|
||||
>
|
||||
<span class="text-uppercase" v-if="settings.search_books_or">{{ $t("or") }}</span>
|
||||
<span class="text-uppercase" v-else>{{ $t("and") }}</span>
|
||||
</b-form-checkbox>
|
||||
</b-input-group-text>
|
||||
</b-input-group-append>
|
||||
@ -217,103 +208,95 @@
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<b-input-group class="mt-2">
|
||||
<treeselect v-model="settings.search_ratings" :options="ratingOptions" :flat="true"
|
||||
:placeholder="$t('Ratings')" :searchable="false"
|
||||
<treeselect
|
||||
v-model="settings.search_ratings"
|
||||
:options="ratingOptions"
|
||||
:flat="true"
|
||||
:placeholder="$t('Ratings')"
|
||||
:searchable="false"
|
||||
@input="refreshData(false)"
|
||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"/>
|
||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||
/>
|
||||
<b-input-group-append>
|
||||
<b-input-group-text style="width:85px">
|
||||
</b-input-group-text>
|
||||
<b-input-group-text style="width: 85px"> </b-input-group-text>
|
||||
</b-input-group-append>
|
||||
</b-input-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</b-collapse>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col col-md-12 text-right" style="margin-top: 2vh">
|
||||
<span class="text-muted">
|
||||
{{ $t('Page') }} {{ settings.pagination_page }}/{{ Math.ceil(pagination_count/settings.page_count) }} <a href="#" @click="resetSearch"><i
|
||||
class="fas fa-times-circle"></i> {{ $t('Reset') }}</a>
|
||||
{{ $t("Page") }} {{ settings.pagination_page }}/{{ Math.ceil(pagination_count / settings.page_count) }}
|
||||
<a href="#" @click="resetSearch"><i class="fas fa-times-circle"></i> {{ $t("Reset") }}</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));grid-gap: 0.8rem;" >
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); grid-gap: 0.8rem">
|
||||
<template v-if="!searchFiltered">
|
||||
<recipe-card v-bind:key="`mp_${m.id}`" v-for="m in meal_plans" :recipe="m.recipe"
|
||||
:meal_plan="m" :footer_text="m.meal_type_name"
|
||||
footer_icon="far fa-calendar-alt"></recipe-card>
|
||||
<recipe-card
|
||||
v-bind:key="`mp_${m.id}`"
|
||||
v-for="m in meal_plans"
|
||||
:recipe="m.recipe"
|
||||
:meal_plan="m"
|
||||
:footer_text="m.meal_type_name"
|
||||
footer_icon="far fa-calendar-alt"
|
||||
></recipe-card>
|
||||
</template>
|
||||
<recipe-card v-for="r in recipes" v-bind:key="r.id" :recipe="r"
|
||||
:footer_text="isRecentOrNew(r)[0]"
|
||||
:footer_icon="isRecentOrNew(r)[1]">
|
||||
</recipe-card>
|
||||
<recipe-card v-for="r in recipes" v-bind:key="r.id" :recipe="r" :footer_text="isRecentOrNew(r)[0]" :footer_icon="isRecentOrNew(r)[1]"> </recipe-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="margin-top: 2vh" v-if="!random_search">
|
||||
<div class="col col-md-12">
|
||||
<b-pagination pills
|
||||
v-model="settings.pagination_page"
|
||||
:total-rows="pagination_count"
|
||||
:per-page="settings.page_count"
|
||||
@change="pageChange"
|
||||
align="center">
|
||||
|
||||
<b-pagination pills v-model="settings.pagination_page" :total-rows="pagination_count" :per-page="settings.page_count" @change="pageChange" align="center">
|
||||
</b-pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-2 d-none d-md-block">
|
||||
|
||||
</div>
|
||||
<div class="col-md-2 d-none d-md-block"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import {BootstrapVue} from 'bootstrap-vue'
|
||||
import Vue from "vue"
|
||||
import { BootstrapVue } from "bootstrap-vue"
|
||||
|
||||
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
||||
import moment from 'moment'
|
||||
import _debounce from 'lodash/debounce'
|
||||
import "bootstrap-vue/dist/bootstrap-vue.css"
|
||||
import moment from "moment"
|
||||
import _debounce from "lodash/debounce"
|
||||
|
||||
import VueCookies from 'vue-cookies'
|
||||
import VueCookies from "vue-cookies"
|
||||
|
||||
Vue.use(VueCookies)
|
||||
|
||||
import {ApiMixin, ResolveUrlMixin} from "@/utils/utils";
|
||||
import { ApiMixin, ResolveUrlMixin } from "@/utils/utils"
|
||||
|
||||
import LoadingSpinner from "@/components/LoadingSpinner"; // is this deprecated?
|
||||
import LoadingSpinner from "@/components/LoadingSpinner" // is this deprecated?
|
||||
|
||||
import RecipeCard from "@/components/RecipeCard";
|
||||
import GenericMultiselect from "@/components/GenericMultiselect";
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
||||
import RecipeCard from "@/components/RecipeCard"
|
||||
import GenericMultiselect from "@/components/GenericMultiselect"
|
||||
import Treeselect from "@riophae/vue-treeselect"
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
|
||||
|
||||
Vue.use(BootstrapVue)
|
||||
|
||||
let SETTINGS_COOKIE_NAME = 'search_settings'
|
||||
let SETTINGS_COOKIE_NAME = "search_settings"
|
||||
|
||||
export default {
|
||||
name: 'RecipeSearchView',
|
||||
name: "RecipeSearchView",
|
||||
mixins: [ResolveUrlMixin, ApiMixin],
|
||||
components: {GenericMultiselect, RecipeCard, Treeselect},
|
||||
components: { GenericMultiselect, RecipeCard, Treeselect },
|
||||
data() {
|
||||
return {
|
||||
// this.Models and this.Actions inherited from ApiMixin
|
||||
@ -324,7 +307,7 @@ export default {
|
||||
|
||||
settings_loaded: false,
|
||||
settings: {
|
||||
search_input: '',
|
||||
search_input: "",
|
||||
search_internal: false,
|
||||
search_keywords: [],
|
||||
search_foods: [],
|
||||
@ -344,30 +327,30 @@ export default {
|
||||
},
|
||||
|
||||
pagination_count: 0,
|
||||
random_search: false
|
||||
random_search: false,
|
||||
debug: false,
|
||||
}
|
||||
|
||||
},
|
||||
computed: {
|
||||
ratingOptions: function () {
|
||||
return [
|
||||
{'id': 5, 'label': '⭐⭐⭐⭐⭐' + ' (' + (this.facets.Ratings?.['5.0'] ?? 0) + ')' },
|
||||
{'id': 4, 'label': '⭐⭐⭐⭐ ' + this.$t('and_up') + ' (' + (this.facets.Ratings?.['4.0'] ?? 0) + ')' },
|
||||
{'id': 3, 'label': '⭐⭐⭐ ' + this.$t('and_up') + ' (' + (this.facets.Ratings?.['3.0'] ?? 0) + ')' },
|
||||
{'id': 2, 'label': '⭐⭐ ' + this.$t('and_up') + ' (' + (this.facets.Ratings?.['2.0'] ?? 0) + ')' },
|
||||
{'id': 1, 'label': '⭐ ' + this.$t("and_up") + ' (' + (this.facets.Ratings?.['1.0'] ?? 0) + ')' },
|
||||
{'id': -1, 'label': this.$t('Unrated') + ' (' + (this.facets.Ratings?.['0.0'] ?? 0 )+ ')'},
|
||||
{ id: 5, label: "⭐⭐⭐⭐⭐" + " (" + (this.facets.Ratings?.["5.0"] ?? 0) + ")" },
|
||||
{ id: 4, label: "⭐⭐⭐⭐ " + this.$t("and_up") + " (" + (this.facets.Ratings?.["4.0"] ?? 0) + ")" },
|
||||
{ id: 3, label: "⭐⭐⭐ " + this.$t("and_up") + " (" + (this.facets.Ratings?.["3.0"] ?? 0) + ")" },
|
||||
{ id: 2, label: "⭐⭐ " + this.$t("and_up") + " (" + (this.facets.Ratings?.["2.0"] ?? 0) + ")" },
|
||||
{ id: 1, label: "⭐ " + this.$t("and_up") + " (" + (this.facets.Ratings?.["1.0"] ?? 0) + ")" },
|
||||
{ id: -1, label: this.$t("Unrated") + " (" + (this.facets.Ratings?.["0.0"] ?? 0) + ")" },
|
||||
]
|
||||
},
|
||||
searchFiltered: function () {
|
||||
if (
|
||||
this.settings?.search_input === ''
|
||||
&& this.settings?.search_keywords?.length === 0
|
||||
&& this.settings?.search_foods?.length === 0
|
||||
&& this.settings?.search_books?.length === 0
|
||||
&& this.settings?.pagination_page === 1
|
||||
&& !this.random_search
|
||||
&& this.settings?.search_ratings === undefined
|
||||
this.settings?.search_input === "" &&
|
||||
this.settings?.search_keywords?.length === 0 &&
|
||||
this.settings?.search_foods?.length === 0 &&
|
||||
this.settings?.search_books?.length === 0 &&
|
||||
this.settings?.pagination_page === 1 &&
|
||||
!this.random_search &&
|
||||
this.settings?.search_ratings === undefined
|
||||
) {
|
||||
return false
|
||||
} else {
|
||||
@ -380,55 +363,56 @@ export default {
|
||||
if (this.$cookies.isKey(SETTINGS_COOKIE_NAME)) {
|
||||
this.settings = Object.assign({}, this.settings, this.$cookies.get(SETTINGS_COOKIE_NAME))
|
||||
}
|
||||
let urlParams = new URLSearchParams(window.location.search);
|
||||
let urlParams = new URLSearchParams(window.location.search)
|
||||
|
||||
if (urlParams.has('keyword')) {
|
||||
if (urlParams.has("keyword")) {
|
||||
this.settings.search_keywords = []
|
||||
this.facets.Keywords = []
|
||||
for (let x of urlParams.getAll('keyword')) {
|
||||
for (let x of urlParams.getAll("keyword")) {
|
||||
this.settings.search_keywords.push(Number.parseInt(x))
|
||||
this.facets.Keywords.push({'id':x, 'name': 'loading...'})
|
||||
this.facets.Keywords.push({ id: x, name: "loading..." })
|
||||
}
|
||||
}
|
||||
this.facets.Foods = []
|
||||
for (let x of this.settings.search_foods) {
|
||||
this.facets.Foods.push({'id':x, 'name': 'loading...'})
|
||||
this.facets.Foods.push({ id: x, name: "loading..." })
|
||||
}
|
||||
this.facets.Keywords = []
|
||||
for (let x of this.settings.search_keywords) {
|
||||
this.facets.Keywords.push({'id':x, 'name': 'loading...'})
|
||||
this.facets.Keywords.push({ id: x, name: "loading..." })
|
||||
}
|
||||
this.facets.Books = []
|
||||
for (let x of this.settings.search_books) {
|
||||
this.facets.Books.push({'id':x, 'name': 'loading...'})
|
||||
this.facets.Books.push({ id: x, name: "loading..." })
|
||||
}
|
||||
this.loadMealPlan()
|
||||
this.refreshData(false)
|
||||
})
|
||||
this.$i18n.locale = window.CUSTOM_LOCALE
|
||||
this.debug = localStorage.getItem("DEBUG") || false
|
||||
},
|
||||
watch: {
|
||||
settings: {
|
||||
handler() {
|
||||
this.$cookies.set(SETTINGS_COOKIE_NAME, this.settings, '4h')
|
||||
this.$cookies.set(SETTINGS_COOKIE_NAME, this.settings, "4h")
|
||||
},
|
||||
deep: true
|
||||
deep: true,
|
||||
},
|
||||
'settings.show_meal_plan': function () {
|
||||
"settings.show_meal_plan": function () {
|
||||
this.loadMealPlan()
|
||||
},
|
||||
'settings.meal_plan_days': function () {
|
||||
"settings.meal_plan_days": function () {
|
||||
this.loadMealPlan()
|
||||
},
|
||||
'settings.recently_viewed': function () {
|
||||
"settings.recently_viewed": function () {
|
||||
this.refreshData(false)
|
||||
},
|
||||
'settings.search_input': _debounce(function () {
|
||||
"settings.search_input": _debounce(function () {
|
||||
this.settings.pagination_page = 1
|
||||
this.pagination_count = 0
|
||||
this.refreshData(false)
|
||||
}, 300),
|
||||
'settings.page_count': _debounce(function () {
|
||||
"settings.page_count": _debounce(function () {
|
||||
this.refreshData(false)
|
||||
}, 300),
|
||||
},
|
||||
@ -437,59 +421,59 @@ export default {
|
||||
refreshData: function (random) {
|
||||
this.random_search = random
|
||||
let params = {
|
||||
'query': this.settings.search_input,
|
||||
'keywords': this.settings.search_keywords,
|
||||
'foods': this.settings.search_foods,
|
||||
'rating': this.settings.search_ratings,
|
||||
'books': this.settings.search_books.map(function (A) {
|
||||
return A["id"];
|
||||
query: this.settings.search_input,
|
||||
keywords: this.settings.search_keywords,
|
||||
foods: this.settings.search_foods,
|
||||
rating: this.settings.search_ratings,
|
||||
books: this.settings.search_books.map(function (A) {
|
||||
return A["id"]
|
||||
}),
|
||||
'keywordsOr': this.settings.search_keywords_or,
|
||||
'foodsOr': this.settings.search_foods_or,
|
||||
'booksOr': this.settings.search_books_or,
|
||||
'internal': this.settings.search_internal,
|
||||
'random': this.random_search,
|
||||
'_new': this.settings.sort_by_new,
|
||||
'page': this.settings.pagination_page,
|
||||
'pageSize': this.settings.page_count
|
||||
keywordsOr: this.settings.search_keywords_or,
|
||||
foodsOr: this.settings.search_foods_or,
|
||||
booksOr: this.settings.search_books_or,
|
||||
internal: this.settings.search_internal,
|
||||
random: this.random_search,
|
||||
_new: this.settings.sort_by_new,
|
||||
page: this.settings.pagination_page,
|
||||
pageSize: this.settings.page_count,
|
||||
}
|
||||
if (!this.searchFiltered) {
|
||||
params.options = {'query':{'last_viewed': this.settings.recently_viewed}}
|
||||
params.options = { query: { last_viewed: this.settings.recently_viewed } }
|
||||
}
|
||||
this.genericAPI(this.Models.RECIPE, this.Actions.LIST, params).then(result => {
|
||||
window.scrollTo(0, 0);
|
||||
this.genericAPI(this.Models.RECIPE, this.Actions.LIST, params).then((result) => {
|
||||
window.scrollTo(0, 0)
|
||||
this.pagination_count = result.data.count
|
||||
|
||||
this.facets = result.data.facets
|
||||
if(this.facets?.cache_key) {
|
||||
if (this.facets?.cache_key) {
|
||||
this.getFacets(this.facets.cache_key)
|
||||
}
|
||||
this.recipes = this.removeDuplicates(result.data.results, recipe => recipe.id)
|
||||
if (!this.searchFiltered){
|
||||
this.recipes = this.removeDuplicates(result.data.results, (recipe) => recipe.id)
|
||||
if (!this.searchFiltered) {
|
||||
// if meal plans are being shown - filter out any meal plan recipes from the recipe list
|
||||
let mealPlans = []
|
||||
this.meal_plans.forEach(x => mealPlans.push(x.recipe.id))
|
||||
this.recipes = this.recipes.filter(recipe => !mealPlans.includes(recipe.id))
|
||||
this.meal_plans.forEach((x) => mealPlans.push(x.recipe.id))
|
||||
this.recipes = this.recipes.filter((recipe) => !mealPlans.includes(recipe.id))
|
||||
}
|
||||
})
|
||||
},
|
||||
openRandom: function () {
|
||||
this.refreshData(true)
|
||||
},
|
||||
removeDuplicates: function(data, key) {
|
||||
return [
|
||||
...new Map(data.map(item => [key(item), item])).values()
|
||||
]
|
||||
removeDuplicates: function (data, key) {
|
||||
return [...new Map(data.map((item) => [key(item), item])).values()]
|
||||
},
|
||||
loadMealPlan: function () {
|
||||
if (this.settings.show_meal_plan) {
|
||||
let params = {
|
||||
'options': {'query':{
|
||||
'from_date': moment().format('YYYY-MM-DD'),
|
||||
'to_date': moment().add(this.settings.meal_plan_days, 'days').format('YYYY-MM-DD')
|
||||
}}
|
||||
options: {
|
||||
query: {
|
||||
from_date: moment().format("YYYY-MM-DD"),
|
||||
to_date: moment().add(this.settings.meal_plan_days, "days").format("YYYY-MM-DD"),
|
||||
},
|
||||
},
|
||||
}
|
||||
this.genericAPI(this.Models.MEAL_PLAN, this.Actions.LIST, params).then(result => {
|
||||
this.genericAPI(this.Models.MEAL_PLAN, this.Actions.LIST, params).then((result) => {
|
||||
this.meal_plans = result.data
|
||||
})
|
||||
} else {
|
||||
@ -501,7 +485,7 @@ export default {
|
||||
this.refreshData(false)
|
||||
},
|
||||
resetSearch: function () {
|
||||
this.settings.search_input = ''
|
||||
this.settings.search_input = ""
|
||||
this.settings.search_internal = false
|
||||
this.settings.search_keywords = []
|
||||
this.settings.search_foods = []
|
||||
@ -515,20 +499,20 @@ export default {
|
||||
this.refreshData(false)
|
||||
},
|
||||
isAdvancedSettingsSet() {
|
||||
return ((this.settings.search_keywords.length + this.settings.search_foods.length + this.settings.search_books.length) > 0)
|
||||
return this.settings.search_keywords.length + this.settings.search_foods.length + this.settings.search_books.length > 0
|
||||
},
|
||||
normalizer(node) {
|
||||
let count = (node?.count ? ' (' + node.count + ')' : '')
|
||||
let count = node?.count ? " (" + node.count + ")" : ""
|
||||
return {
|
||||
id: node.id,
|
||||
label: node.name + count,
|
||||
children: node.children,
|
||||
isDefaultExpanded: node.isDefaultExpanded
|
||||
isDefaultExpanded: node.isDefaultExpanded,
|
||||
}
|
||||
},
|
||||
isRecentOrNew: function(x) {
|
||||
let recent_recipe = [this.$t('Recently_Viewed'), "fas fa-eye"]
|
||||
let new_recipe = [this.$t('New_Recipe'), "fas fa-splotch"]
|
||||
isRecentOrNew: function (x) {
|
||||
let recent_recipe = [this.$t("Recently_Viewed"), "fas fa-eye"]
|
||||
let new_recipe = [this.$t("New_Recipe"), "fas fa-splotch"]
|
||||
if (x.new) {
|
||||
return new_recipe
|
||||
} else if (this.facets.Recent.includes(x.id)) {
|
||||
@ -537,18 +521,43 @@ export default {
|
||||
return [undefined, undefined]
|
||||
}
|
||||
},
|
||||
getFacets: function(hash) {
|
||||
this.genericGetAPI('api_get_facets', {hash: hash}).then((response) => {
|
||||
this.facets = {...this.facets, ...response.data.facets}
|
||||
getFacets: function (hash) {
|
||||
this.genericGetAPI("api_get_facets", { hash: hash }).then((response) => {
|
||||
this.facets = { ...this.facets, ...response.data.facets }
|
||||
})
|
||||
},
|
||||
showSQL: function () {
|
||||
// TODO refactor this so that it isn't a total copy of refreshData
|
||||
let params = {
|
||||
query: this.settings.search_input,
|
||||
keywords: this.settings.search_keywords,
|
||||
foods: this.settings.search_foods,
|
||||
rating: this.settings.search_ratings,
|
||||
books: this.settings.search_books.map(function (A) {
|
||||
return A["id"]
|
||||
}),
|
||||
keywordsOr: this.settings.search_keywords_or,
|
||||
foodsOr: this.settings.search_foods_or,
|
||||
booksOr: this.settings.search_books_or,
|
||||
internal: this.settings.search_internal,
|
||||
random: this.random_search,
|
||||
_new: this.settings.sort_by_new,
|
||||
page: this.settings.pagination_page,
|
||||
pageSize: this.settings.page_count,
|
||||
}
|
||||
if (!this.searchFiltered) {
|
||||
params.options = { query: { last_viewed: this.settings.recently_viewed, debug: true } }
|
||||
} else {
|
||||
params.options = { query: { debug: true } }
|
||||
}
|
||||
this.genericAPI(this.Models.RECIPE, this.Actions.LIST, params).then((result) => {
|
||||
console.log(result.data)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
<style></style>
|
||||
|
@ -206,5 +206,6 @@
|
||||
"Auto_Planner": "Auto-Planner",
|
||||
"New_Cookbook": "New cookbook",
|
||||
"Hide_Keyword": "Hide keywords",
|
||||
"Clear": "Clear"
|
||||
"Clear": "Clear",
|
||||
"show_sql": "Show SQL"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user