This commit is contained in:
Chris Scoggins
2022-02-01 10:13:58 -06:00
parent 203ff1a6ec
commit c45bf3a994
10 changed files with 159 additions and 173 deletions

View File

@ -38,7 +38,7 @@ class RecipeSearch():
self._search_prefs = request.user.searchpreference
else:
self._search_prefs = SearchPreference()
self._string = params.get('query').strip() if params.get('query', None) else None
self._string = params.get('string').strip() if params.get('string', None) else None
self._rating = self._params.get('rating', None)
self._keywords = {
'or': self._params.get('keywords_or', None),

View File

@ -11,7 +11,7 @@ class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('cookbook', '0167_userpreference_left_handed'),
('cookbook', '0168_add_unit_searchfields'),
]
operations = [

View File

@ -632,7 +632,7 @@ class RecipeViewSet(viewsets.ModelViewSet):
pagination_class = RecipePagination
query_params = [
QueryParam(name='query', description=_('Query string matched (fuzzy) against recipe name. In the future also fulltext search.')),
QueryParam(name='string', description=_('Query string matched (fuzzy) against recipe name. In the future also fulltext search.')),
QueryParam(name='keywords', description=_('ID of keyword a recipe should have. For multiple repeat parameter. Equivalent to keywords_or'), qtype='int'),
QueryParam(name='keywords_or', description=_('Keyword IDs, repeat for multiple. Return recipes with any of the keywords'), qtype='int'),
QueryParam(name='keywords_and', description=_('Keyword IDs, repeat for multiple. Return recipes with all of the keywords.'), qtype='int'),

View File

@ -997,7 +997,7 @@ export default {
...this.addFields("foods"),
...this.addFields("books"),
units: this.search.search_units,
query: this.search.search_input,
string: this.search.search_input,
rating: rating,
internal: this.search.search_internal,
random: this.random_search,

View File

@ -3,28 +3,16 @@
<div class="cv-header-nav d-none d-md-block">
<b-button-toolbar key-nav aria-label="Toolbar with button groups">
<b-button-group class="mx-1">
<b-button v-html="'<<'" @click="onInput(headerProps.previousPeriod)" class="text-white" v-b-tooltip.hover.top
:title="$t('Previous_Period')"></b-button>
<b-button v-html="'<'" @click="onDayBack" class="text-white" v-b-tooltip.hover.top
:title="$t('Previous_Day')"></b-button>
<b-button v-html="'<<'" @click="onInput(headerProps.previousPeriod)" class="text-white" v-b-tooltip.hover.top :title="$t('Previous_Period')"></b-button>
<b-button v-html="'<'" @click="onDayBack" class="text-white" v-b-tooltip.hover.top :title="$t('Previous_Day')"></b-button>
</b-button-group>
<b-button-group class="mx-1">
<b-button @click="onInput(headerProps.currentPeriod)" class="text-white" v-b-tooltip.hover.top
:title="$t('Current_Period')"><i class="fas fa-home"></i>
</b-button>
<b-form-datepicker
button-only
button-variant="secondary"
v-b-tooltip.hover.top
:title="$t('Date')"
@context="dateSelect" class="text-white"
></b-form-datepicker>
<b-button @click="onInput(headerProps.currentPeriod)" class="text-white" v-b-tooltip.hover.top :title="$t('Current_Period')"><i class="fas fa-home"></i> </b-button>
<b-form-datepicker button-only button-variant="secondary" v-b-tooltip.hover.top :title="$t('Date')" @context="dateSelect" class="text-white"></b-form-datepicker>
</b-button-group>
<b-button-group class="mx-1">
<b-button v-html="'>'" @click="onDayForward" class="text-white" v-b-tooltip.hover.top
:title="$t('Next_Day')"></b-button>
<b-button v-html="'>>'" @click="onInput(headerProps.nextPeriod)" class="text-white" v-b-tooltip.hover.top
:title="$t('Next_Period')"></b-button>
<b-button v-html="'>'" @click="onDayForward" class="text-white" v-b-tooltip.hover.top :title="$t('Next_Day')"></b-button>
<b-button v-html="'>>'" @click="onInput(headerProps.nextPeriod)" class="text-white" v-b-tooltip.hover.top :title="$t('Next_Period')"></b-button>
</b-button-group>
</b-button-toolbar>
</div>
@ -34,26 +22,20 @@
<div class="actionArea pt-1 pb-1 d-none d-lg-flex">
<span class="period-span-1 pt-1 pb-1 pl-1 pr-1 d-none d-xl-inline-flex text-body align-items-center">
<small>Period:</small>
<b-form-select
class="ml-1"
id="UomInput"
v-model="settings.displayPeriodUom"
:options="options.displayPeriodUom"
></b-form-select>
<b-form-select class="ml-1" id="UomInput" v-model="settings.displayPeriodUom" :options="options.displayPeriodUom"></b-form-select>
</span>
<span class="period-span-2 pt-1 pb-1 pl-1 pr-1 mr-1 ml-1 d-none d-xl-inline-flex text-body align-items-center">
<small>Periods:</small>
<b-form-select
class="ml-1"
id="UomInput"
v-model="settings.displayPeriodCount"
:options="options.displayPeriodCount"
></b-form-select>
<b-form-select class="ml-1" id="UomInput" v-model="settings.displayPeriodCount" :options="options.displayPeriodCount"></b-form-select>
</span>
<span class="delete-area text-danger p-1 mr-2 ml-1 d-none d-sm-flex align-items-center"
<span
class="delete-area text-danger p-1 mr-2 ml-1 d-none d-sm-flex align-items-center"
@drop.prevent="onDeleteDrop($event)"
@dragenter.prevent="onDeleteDragEnter($event)" @dragleave.prevent="onDeleteDragLeave($event)"
@dragover.prevent="onDeleteDragEnter"><i class="fa fa-trash"></i> {{ $t('Drag_Here_To_Delete') }}</span>
@dragenter.prevent="onDeleteDragEnter($event)"
@dragleave.prevent="onDeleteDragLeave($event)"
@dragover.prevent="onDeleteDragEnter"
><i class="fa fa-trash"></i> {{ $t("Drag_Here_To_Delete") }}</span
>
</div>
</div>
</template>
@ -66,9 +48,9 @@ export default {
return this.settings_prop
},
set: function (value) {
this.$emit('change', value)
}
}
this.$emit("change", value)
},
},
},
props: {
headerProps: {
@ -76,12 +58,12 @@ export default {
required: true,
},
options: {},
previousYearLabel: {type: String, default: "<<"},
previousPeriodLabel: {type: String, default: "<"},
nextPeriodLabel: {type: String, default: ">"},
nextYearLabel: {type: String, default: ">>"},
iCalUrl: {type: String, default: ""},
settings_prop: {}
previousYearLabel: { type: String, default: "<<" },
previousPeriodLabel: { type: String, default: "<" },
nextPeriodLabel: { type: String, default: ">" },
nextYearLabel: { type: String, default: ">>" },
iCalUrl: { type: String, default: "" },
settings_prop: {},
},
methods: {
onDayForward() {
@ -140,22 +122,22 @@ export default {
.period-span-1 {
margin-left: auto;
order: 1;
user-select: none
user-select: none;
}
.period-span-2 {
order: 2;
user-select: none
user-select: none;
}
.delete-area {
border-style: dotted;
order: 3;
user-select: none
user-select: none;
}
.delete-area.draghover {
box-shadow: inset 0 0 0.1em 0.1em #A7240E !important;
box-shadow: inset 0 0 0.1em 0.1em #a7240e !important;
}
.cv-header,

View File

@ -131,8 +131,9 @@ export default {
let flat_items = []
let item = undefined
let label = this.form.list_label.split("::")
this.list_label = label[1]
itemlist.forEach((x) => {
item = {}
item = { ...x }
for (const [k, v] of Object.entries(x)) {
if (k == label[0]) {
item["id"] = v.id
@ -144,6 +145,7 @@ export default {
flat_items.push(item)
})
this.first_run = false
return flat_items
},
unflattenItem: function (itemList) {

View File

@ -55,6 +55,7 @@
</b-input-group-prepend>
<b-form-spinbutton min="1" v-model="recipe_servings" inline style="height: 3em"></b-form-spinbutton>
<CustomInputSpinButton v-model.number="recipe_servings" style="height: 3em" />
<b-input-group-append>
<b-button variant="secondary" @click="$bvModal.hide(`shopping_${modal_id}`)">{{ $t("Cancel") }} </b-button>
@ -75,10 +76,11 @@ const { ApiApiFactory } = require("@/utils/openapi/api")
import { StandardToasts } from "@/utils/utils"
import IngredientsCard from "@/components/IngredientsCard"
import LoadingSpinner from "@/components/LoadingSpinner"
import CustomInputSpinButton from "@/components/CustomInputSpinButton"
export default {
name: "ShoppingModal",
components: { IngredientsCard, LoadingSpinner },
components: { IngredientsCard, LoadingSpinner, CustomInputSpinButton },
mixins: [],
props: {
recipe: { required: true, type: Object },

View File

@ -71,7 +71,7 @@ Vue.prototype.moment = moment
export default {
name: "RecipeCard",
mixins: [ResolveUrlMixin],
components: { LastCooked, RecipeRating, KeywordsComponent, RecipeContextMenu, IngredientsCard },
components: { LastCooked, RecipeRating, KeywordsComponent, "recipe-context-menu": RecipeContextMenu, IngredientsCard },
props: {
recipe: Object,
meal_plan: Object,

View File

@ -59,7 +59,7 @@ export class Models {
// MODELS - inherits and takes precedence over MODEL_TYPES and ACTIONS
static FOOD = {
name: "Food", // *OPTIONAL* : parameters will be built model -> model_type -> default
name: i18n.t("Food"), // *OPTIONAL* : parameters will be built model -> model_type -> default
apiName: "Food", // *REQUIRED* : the name that is used in api.ts for this model
model_type: this.TREE, // *OPTIONAL* : model specific params for api, if not present will attempt modeltype_create then default_create
paginated: true,
@ -148,7 +148,7 @@ export class Models {
}
static KEYWORD = {
name: "Keyword", // *OPTIONAL: parameters will be built model -> model_type -> default
name: i18n.t("Keyword"), // *OPTIONAL: parameters will be built model -> model_type -> default
apiName: "Keyword",
model_type: this.TREE,
paginated: true,
@ -191,7 +191,7 @@ export class Models {
}
static UNIT = {
name: "Unit",
name: i18n.t("Unit"),
apiName: "Unit",
paginated: true,
create: {
@ -217,7 +217,7 @@ export class Models {
}
static SHOPPING_LIST = {
name: "Shopping_list",
name: i18n.t("Shopping_list"),
apiName: "ShoppingListEntry",
list: {
params: ["id", "checked", "supermarket", "options"],
@ -246,7 +246,7 @@ export class Models {
}
static RECIPE_BOOK = {
name: "Recipe_Book",
name: i18n.t("Recipe_Book"),
apiName: "RecipeBook",
create: {
params: [["name", "description", "icon", "filter"]],
@ -283,7 +283,7 @@ export class Models {
}
static SHOPPING_CATEGORY = {
name: "Shopping_Category",
name: i18n.t("Shopping_Category"),
apiName: "SupermarketCategory",
create: {
params: [["name", "description"]],
@ -307,7 +307,7 @@ export class Models {
}
static SHOPPING_CATEGORY_RELATION = {
name: "Shopping_Category_Relation",
name: i18n.t("Shopping_Category_Relation"),
apiName: "SupermarketCategoryRelation",
create: {
params: [["category", "supermarket", "order"]],
@ -331,7 +331,7 @@ export class Models {
}
static SUPERMARKET = {
name: "Supermarket",
name: i18n.t("Supermarket"),
apiName: "Supermarket",
ordered_tags: [{ field: "category_to_supermarket", label: "category::name", color: "info" }],
create: {
@ -374,7 +374,7 @@ export class Models {
}
static AUTOMATION = {
name: "Automation",
name: i18n.t("Automation"),
apiName: "Automation",
paginated: true,
list: {
@ -437,11 +437,11 @@ export class Models {
}
static RECIPE = {
name: "Recipe",
name: i18n.t("Recipe"),
apiName: "Recipe",
list: {
params: [
"query",
"string",
"keywords",
"keywords_or",
"keywords_and",
@ -503,7 +503,7 @@ export class Models {
},
}
static USER_NAME = {
name: "User",
name: i18n.t("User"),
apiName: "User",
list: {
params: ["filter_list"],
@ -511,7 +511,7 @@ export class Models {
}
static MEAL_TYPE = {
name: "Meal_Type",
name: i18n.t("Meal_Type"),
apiName: "MealType",
list: {
params: ["filter_list"],
@ -519,7 +519,7 @@ export class Models {
}
static MEAL_PLAN = {
name: "Meal_Plan",
name: i18n.t("Meal_Plan"),
apiName: "MealPlan",
list: {
params: ["options"],
@ -527,7 +527,7 @@ export class Models {
}
static USERFILE = {
name: "File",
name: i18n.t("File"),
apiName: "UserFile",
paginated: false,
list: {
@ -556,13 +556,13 @@ export class Models {
},
}
static USER = {
name: "User",
name: i18n.t("User"),
apiName: "User",
paginated: false,
}
static STEP = {
name: "Step",
name: i18n.t("Step"),
apiName: "Step",
list: {
params: ["recipe", "query", "page", "pageSize", "options"],

View File

@ -5459,7 +5459,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} [string] Query string matched (fuzzy) against recipe name. In the future also fulltext search.
* @param {number} [keywords] ID of keyword a recipe should have. For multiple repeat parameter. Equivalent to keywords_or
* @param {number} [keywordsOr] Keyword IDs, repeat for multiple. Return recipes with any of the keywords
* @param {number} [keywordsAnd] Keyword IDs, repeat for multiple. Return recipes with all of the keywords.
@ -5488,7 +5488,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listRecipes: async (query?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: number, page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
listRecipes: async (string?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: number, 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);
@ -5501,8 +5501,8 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
if (query !== undefined) {
localVarQueryParameter['query'] = query;
if (string !== undefined) {
localVarQueryParameter['string'] = string;
}
if (keywords !== undefined) {
@ -10045,7 +10045,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} [string] Query string matched (fuzzy) against recipe name. In the future also fulltext search.
* @param {number} [keywords] ID of keyword a recipe should have. For multiple repeat parameter. Equivalent to keywords_or
* @param {number} [keywordsOr] Keyword IDs, repeat for multiple. Return recipes with any of the keywords
* @param {number} [keywordsAnd] Keyword IDs, repeat for multiple. Return recipes with all of the keywords.
@ -10074,8 +10074,8 @@ export const ApiApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listRecipes(query?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: number, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2004>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listRecipes(query, keywords, keywordsOr, keywordsAnd, keywordsOrNot, keywordsAndNot, foods, foodsOr, foodsAnd, foodsOrNot, foodsAndNot, units, rating, books, booksOr, booksAnd, booksOrNot, booksAndNot, internal, random, _new, timescooked, lastcooked, makenow, page, pageSize, options);
async listRecipes(string?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: number, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2004>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listRecipes(string, keywords, keywordsOr, keywordsAnd, keywordsOrNot, keywordsAndNot, foods, foodsOr, foodsAnd, foodsOrNot, foodsAndNot, units, rating, books, booksOr, booksAnd, booksOrNot, booksAndNot, internal, random, _new, timescooked, lastcooked, makenow, page, pageSize, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
@ -11800,7 +11800,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} [string] Query string matched (fuzzy) against recipe name. In the future also fulltext search.
* @param {number} [keywords] ID of keyword a recipe should have. For multiple repeat parameter. Equivalent to keywords_or
* @param {number} [keywordsOr] Keyword IDs, repeat for multiple. Return recipes with any of the keywords
* @param {number} [keywordsAnd] Keyword IDs, repeat for multiple. Return recipes with all of the keywords.
@ -11829,8 +11829,8 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listRecipes(query?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: number, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2004> {
return localVarFp.listRecipes(query, keywords, keywordsOr, keywordsAnd, keywordsOrNot, keywordsAndNot, foods, foodsOr, foodsAnd, foodsOrNot, foodsAndNot, units, rating, books, booksOr, booksAnd, booksOrNot, booksAndNot, internal, random, _new, timescooked, lastcooked, makenow, page, pageSize, options).then((request) => request(axios, basePath));
listRecipes(string?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: number, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2004> {
return localVarFp.listRecipes(string, keywords, keywordsOr, keywordsAnd, keywordsOrNot, keywordsAndNot, foods, foodsOr, foodsAnd, foodsOrNot, foodsAndNot, units, rating, books, booksOr, booksAnd, booksOrNot, booksAndNot, internal, random, _new, timescooked, lastcooked, makenow, page, pageSize, options).then((request) => request(axios, basePath));
},
/**
*
@ -13582,7 +13582,7 @@ export class ApiApi extends BaseAPI {
/**
*
* @param {string} [query] Query string matched (fuzzy) against recipe name. In the future also fulltext search.
* @param {string} [string] Query string matched (fuzzy) against recipe name. In the future also fulltext search.
* @param {number} [keywords] ID of keyword a recipe should have. For multiple repeat parameter. Equivalent to keywords_or
* @param {number} [keywordsOr] Keyword IDs, repeat for multiple. Return recipes with any of the keywords
* @param {number} [keywordsAnd] Keyword IDs, repeat for multiple. Return recipes with all of the keywords.
@ -13612,8 +13612,8 @@ export class ApiApi extends BaseAPI {
* @throws {RequiredError}
* @memberof ApiApi
*/
public listRecipes(query?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: number, page?: number, pageSize?: number, options?: any) {
return ApiApiFp(this.configuration).listRecipes(query, keywords, keywordsOr, keywordsAnd, keywordsOrNot, keywordsAndNot, foods, foodsOr, foodsAnd, foodsOrNot, foodsAndNot, units, rating, books, booksOr, booksAnd, booksOrNot, booksAndNot, internal, random, _new, timescooked, lastcooked, makenow, page, pageSize, options).then((request) => request(this.axios, this.basePath));
public listRecipes(string?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: number, page?: number, pageSize?: number, options?: any) {
return ApiApiFp(this.configuration).listRecipes(string, keywords, keywordsOr, keywordsAnd, keywordsOrNot, keywordsAndNot, foods, foodsOr, foodsAnd, foodsOrNot, foodsAndNot, units, rating, books, booksOr, booksAnd, booksOrNot, booksAndNot, internal, random, _new, timescooked, lastcooked, makenow, page, pageSize, options).then((request) => request(this.axios, this.basePath));
}
/**