finished unit page

This commit is contained in:
smilerz 2021-09-06 14:00:32 -05:00
parent 84744560e0
commit c9d1a9b551
17 changed files with 76 additions and 31 deletions

View File

@ -20,6 +20,7 @@ def search_recipes(request, queryset, params):
search_keywords = params.getlist('keywords', [])
search_foods = params.getlist('foods', [])
search_books = params.getlist('books', [])
search_units = params.get('units', None)
# TODO I think default behavior should be 'AND' which is how most sites operate with facet/filters based on results
search_keywords_or = params.get('keywords_or', True)
@ -160,6 +161,10 @@ def search_recipes(request, queryset, params):
for k in search_books:
queryset = queryset.filter(recipebookentry__book__id=k)
# probably only useful in Unit list view, so keeping it simple
if search_units:
queryset = queryset.filter(steps__ingredients__unit__id=search_units)
if search_internal == 'true':
queryset = queryset.filter(internal=True)

View File

@ -24,6 +24,11 @@ class RecipeSchema(AutoSchema):
"description": 'Id of food a recipe should have. For multiple repeat parameter.',
'schema': {'type': 'string', },
})
parameters.append({
"name": 'units', "in": "query", "required": False,
"description": 'Id of unit a recipe should have.',
'schema': {'type': 'int', },
})
parameters.append({
"name": 'books', "in": "query", "required": False,
"description": 'Id of book a recipe should have. For multiple repeat parameter.',
@ -85,3 +90,18 @@ class TreeSchema(AutoSchema):
'schema': {'type': 'int', },
})
return parameters
class FilterSchema(AutoSchema):
def get_path_parameters(self, path, method):
if not is_list_view(path, method, self.view):
return super(FilterSchema, self).get_path_parameters(path, method)
api_name = path.split('/')[2]
parameters = super().get_path_parameters(path, method)
parameters.append({
"name": 'query', "in": "query", "required": False,
"description": 'Query string matched against {} name.'.format(api_name),
'schema': {'type': 'string', },
})
return parameters

View File

@ -1 +1 @@
.shake[data-v-d394ab04]{-webkit-animation:shake-data-v-d394ab04 .82s cubic-bezier(.36,.07,.19,.97) both;animation:shake-data-v-d394ab04 .82s cubic-bezier(.36,.07,.19,.97) both;transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;perspective:1000px}@-webkit-keyframes shake-data-v-d394ab04{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}@keyframes shake-data-v-d394ab04{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}
.shake[data-v-021606fa]{-webkit-animation:shake-data-v-021606fa .82s cubic-bezier(.36,.07,.19,.97) both;animation:shake-data-v-021606fa .82s cubic-bezier(.36,.07,.19,.97) both;transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;perspective:1000px}@-webkit-keyframes shake-data-v-021606fa{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}@keyframes shake-data-v-021606fa{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -48,7 +48,7 @@ from cookbook.models import (CookLog, Food, Ingredient, Keyword, MealPlan,
from cookbook.provider.dropbox import Dropbox
from cookbook.provider.local import Local
from cookbook.provider.nextcloud import Nextcloud
from cookbook.schemas import RecipeSchema, TreeSchema
from cookbook.schemas import FilterSchema, RecipeSchema, TreeSchema
from cookbook.serializer import (FoodSerializer, IngredientSerializer,
KeywordSerializer, MealPlanSerializer,
MealTypeSerializer, RecipeBookSerializer,
@ -98,6 +98,8 @@ class DefaultPagination(PageNumberPagination):
class FuzzyFilterMixin(ViewSetMixin):
schema = FilterSchema()
def get_queryset(self):
self.queryset = self.queryset.filter(space=self.request.space)
query = self.request.query_params.get('query', None)

View File

@ -146,7 +146,7 @@ def unit(request):
"title": _("Units"),
"config": {
'model': "UNIT", # *REQUIRED* name of the model in models.js
# 'recipe_param': 'units' # *OPTIONAL* name of the listRecipes parameter if filtering on this attribute
'recipe_param': 'units' # *OPTIONAL* name of the listRecipes parameter if filtering on this attribute
}
}
)

View File

@ -21,8 +21,8 @@
:item=i
:item_type="this_model.name"
:draggable="true"
:merge="true"
:move="true"
:merge="this_model['merge'] !== false"
:move="this_model['move'] !== false"
@item-action="startAction($event, 'left')">
<!-- foods can also be a recipe, show link to the recipe if it exists -->
<template v-slot:upper-right>
@ -41,8 +41,8 @@
:item=i
:item_type="this_model.name"
:draggable="true"
:merge="true"
:move="true"
:merge="this_model['merge'] !== false"
:move="this_model['move'] !== false"
@item-action="startAction($event, 'right')">
<!-- foods can also be a recipe, show link to the recipe if it exists -->
<template v-slot:upper-right>

View File

@ -19,7 +19,7 @@
<h5 class="m-0 mt-1 text-truncate">{{ item[title] }}</h5>
<div class= "m-0 text-truncate">{{ item[subtitle] }}</div>
<div class="mt-auto mb-1 d-flex flex-row justify-content-end">
<div v-if="item[child_count] !=0" class="mx-2 btn btn-link btn-sm"
<div v-if="item[child_count]" class="mx-2 btn btn-link btn-sm"
style="z-index: 800;" v-on:click="$emit('item-action',{'action':'get-children','source':item})">
<div v-if="!item.show_children">{{ item[child_count] }} {{ item_type }}</div>
<div v-else>{{ text.hide_children }}</div>
@ -112,6 +112,7 @@ export default {
recipes: {type: String, default: 'recipes'},
move: {type: Boolean, default: false},
merge: {type: Boolean, default: false},
tree: {type: Boolean, default: false},
},
data() {
return {

View File

@ -124,5 +124,6 @@
"tree_root": "Root of Tree",
"Icon": "Icon",
"Unit": "Unit",
"No_Results": "No Results"
"No_Results": "No Results",
"New_Unit": "New Unit"
}

View File

@ -175,7 +175,7 @@ export class Models {
'name': i18n.t('Recipe'),
'apiName': 'Recipe',
'list': {
'params': ['query', 'keywords', 'foods', 'books', 'keywordsOr', 'foodsOr', 'booksOr', 'internal', 'random', '_new', 'page', 'pageSize', 'options'],
'params': ['query', 'keywords', 'foods', 'units', 'books', 'keywordsOr', 'foodsOr', 'booksOr', 'internal', 'random', '_new', 'page', 'pageSize', 'options'],
'config': {
'foods': {'type':'string'},
'keywords': {'type': 'string'},

View File

@ -4394,6 +4394,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
* @param {string} [query] Query string matched (fuzzy) against recipe name. In the future also fulltext search.
* @param {string} [keywords] Id of keyword a recipe should have. For multiple repeat parameter.
* @param {string} [foods] Id of food a recipe should have. For multiple repeat parameter.
* @param {number} [units] Id of unit a recipe should have.
* @param {string} [books] Id of book a recipe should have. For multiple repeat parameter.
* @param {string} [keywordsOr] If recipe should have all (AND) or any (OR) of the provided keywords.
* @param {string} [foodsOr] If recipe should have all (AND) or any (OR) any of the provided foods.
@ -4406,7 +4407,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listRecipes: async (query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
listRecipes: async (query?: string, keywords?: string, foods?: string, units?: number, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
const localVarPath = `/api/recipe/`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -4431,6 +4432,10 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
localVarQueryParameter['foods'] = foods;
}
if (units !== undefined) {
localVarQueryParameter['units'] = units;
}
if (books !== undefined) {
localVarQueryParameter['books'] = books;
}
@ -4780,12 +4785,13 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
},
/**
*
* @param {string} [query] Query string matched against unit name.
* @param {number} [page] A page number within the paginated result set.
* @param {number} [pageSize] Number of results to return per page.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listUnits: async (page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
listUnits: async (query?: string, page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
const localVarPath = `/api/unit/`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -4798,6 +4804,10 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
if (query !== undefined) {
localVarQueryParameter['query'] = query;
}
if (page !== undefined) {
localVarQueryParameter['page'] = page;
}
@ -8425,6 +8435,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
* @param {string} [query] Query string matched (fuzzy) against recipe name. In the future also fulltext search.
* @param {string} [keywords] Id of keyword a recipe should have. For multiple repeat parameter.
* @param {string} [foods] Id of food a recipe should have. For multiple repeat parameter.
* @param {number} [units] Id of unit a recipe should have.
* @param {string} [books] Id of book a recipe should have. For multiple repeat parameter.
* @param {string} [keywordsOr] If recipe should have all (AND) or any (OR) of the provided keywords.
* @param {string} [foodsOr] If recipe should have all (AND) or any (OR) any of the provided foods.
@ -8437,8 +8448,8 @@ export const ApiApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listRecipes(query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2003>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listRecipes(query, keywords, foods, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options);
async listRecipes(query?: string, keywords?: string, foods?: string, units?: number, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2003>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listRecipes(query, keywords, foods, units, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
@ -8535,13 +8546,14 @@ export const ApiApiFp = function(configuration?: Configuration) {
},
/**
*
* @param {string} [query] Query string matched against unit name.
* @param {number} [page] A page number within the paginated result set.
* @param {number} [pageSize] Number of results to return per page.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listUnits(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2001>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listUnits(page, pageSize, options);
async listUnits(query?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2001>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listUnits(query, page, pageSize, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
@ -9984,6 +9996,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
* @param {string} [query] Query string matched (fuzzy) against recipe name. In the future also fulltext search.
* @param {string} [keywords] Id of keyword a recipe should have. For multiple repeat parameter.
* @param {string} [foods] Id of food a recipe should have. For multiple repeat parameter.
* @param {number} [units] Id of unit a recipe should have.
* @param {string} [books] Id of book a recipe should have. For multiple repeat parameter.
* @param {string} [keywordsOr] If recipe should have all (AND) or any (OR) of the provided keywords.
* @param {string} [foodsOr] If recipe should have all (AND) or any (OR) any of the provided foods.
@ -9996,8 +10009,8 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listRecipes(query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2003> {
return localVarFp.listRecipes(query, keywords, foods, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options).then((request) => request(axios, basePath));
listRecipes(query?: string, keywords?: string, foods?: string, units?: number, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2003> {
return localVarFp.listRecipes(query, keywords, foods, units, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options).then((request) => request(axios, basePath));
},
/**
*
@ -10083,13 +10096,14 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
},
/**
*
* @param {string} [query] Query string matched against unit name.
* @param {number} [page] A page number within the paginated result set.
* @param {number} [pageSize] Number of results to return per page.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listUnits(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2001> {
return localVarFp.listUnits(page, pageSize, options).then((request) => request(axios, basePath));
listUnits(query?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2001> {
return localVarFp.listUnits(query, page, pageSize, options).then((request) => request(axios, basePath));
},
/**
*
@ -11566,6 +11580,7 @@ export class ApiApi extends BaseAPI {
* @param {string} [query] Query string matched (fuzzy) against recipe name. In the future also fulltext search.
* @param {string} [keywords] Id of keyword a recipe should have. For multiple repeat parameter.
* @param {string} [foods] Id of food a recipe should have. For multiple repeat parameter.
* @param {number} [units] Id of unit a recipe should have.
* @param {string} [books] Id of book a recipe should have. For multiple repeat parameter.
* @param {string} [keywordsOr] If recipe should have all (AND) or any (OR) of the provided keywords.
* @param {string} [foodsOr] If recipe should have all (AND) or any (OR) any of the provided foods.
@ -11579,8 +11594,8 @@ export class ApiApi extends BaseAPI {
* @throws {RequiredError}
* @memberof ApiApi
*/
public listRecipes(query?: string, keywords?: string, foods?: string, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any) {
return ApiApiFp(this.configuration).listRecipes(query, keywords, foods, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options).then((request) => request(this.axios, this.basePath));
public listRecipes(query?: string, keywords?: string, foods?: string, units?: number, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any) {
return ApiApiFp(this.configuration).listRecipes(query, keywords, foods, units, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options).then((request) => request(this.axios, this.basePath));
}
/**
@ -11687,14 +11702,15 @@ export class ApiApi extends BaseAPI {
/**
*
* @param {string} [query] Query string matched against unit name.
* @param {number} [page] A page number within the paginated result set.
* @param {number} [pageSize] Number of results to return per page.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof ApiApi
*/
public listUnits(page?: number, pageSize?: number, options?: any) {
return ApiApiFp(this.configuration).listUnits(page, pageSize, options).then((request) => request(this.axios, this.basePath));
public listUnits(query?: string, page?: number, pageSize?: number, options?: any) {
return ApiApiFp(this.configuration).listUnits(query, page, pageSize, options).then((request) => request(this.axios, this.basePath));
}
/**