Frontend Fixes + Adjust Caddyfile (#518)

* token error handling

* Add additional settings to recipes

* fixes #515

* remove index.html

Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
Hayden 2021-06-14 19:37:38 -08:00 committed by GitHub
parent 17a7d0b31e
commit d7c883feca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 48 additions and 319 deletions

View File

@ -29,7 +29,7 @@
handle {
header @static Cache-Control max-age=31536000
root * /app/dist
try_files {path}.html {path} /index.html
try_files {path}.html {path} /
file_server
}
}

View File

@ -1,42 +0,0 @@
import { recipeIngredient } from "./recipeIngredient";
import { recipeNumber } from "./recipeNumber";
export const ingredientScaler = {
process(ingredientArray, scale) {
console.log(scale);
let workingArray = ingredientArray.map(x =>
ingredientScaler.markIngredient(x)
);
return workingArray.map(x => ingredientScaler.adjustIngredients(x, scale));
},
adjustIngredients(ingredient, scale) {
var scaledQuantity = new recipeNumber(ingredient.quantity).multiply(scale);
const newText = ingredient.text.replace(
ingredient.quantity,
scaledQuantity
);
return { ...ingredient, quantity: scaledQuantity, text: newText };
},
markIngredient(ingredient) {
console.log(ingredient);
const returnVar = ingredient.replace(
/^([\d/?[^\s&]*)(?:&nbsp;|\s)(\w*)/g,
(match, quantity, unit) => {
return `${unit}${quantity},${match}`;
}
);
const split = returnVar.split(",");
const [unit, quantity, match] = split;
console.log("Split", unit, quantity, match);
const n = new recipeNumber(quantity);
const i = new recipeIngredient(n, unit);
const serializedQuantity = n.isFraction() ? n.toImproperFraction() : n;
return {
unit: i,
quantity: serializedQuantity.toString(),
text: match,
};
},
};

View File

@ -1,75 +0,0 @@
export const recipeIngredient = function(quantity, unit) {
this.quantity = quantity;
this.unit = unit;
};
recipeIngredient.prototype.isSingular = function() {
return this.quantity > 0 && this.quantity <= 1;
};
recipeIngredient.prototype.pluralize = function() {
if (this.isSingular()) {
return this.unit;
} else {
return `${this.unit}s`;
}
};
recipeIngredient.prototype.getSingularUnit = function() {
if (this.isSingular()) {
return this.unit;
} else {
return this.unit.replace(/s$/, "");
}
};
recipeIngredient.prototype.toString = function() {
return `${this.quantity.toString()} ${this.pluralize()}`;
};
recipeIngredient.prototype.convertUnits = function() {
const conversion = recipeIngredient.CONVERSIONS[this.unit] || {};
if (conversion.min && this.quantity < conversion.min.value) {
this.unit = conversion.min.next;
this.quantity.multiply(conversion.to[this.unit]);
} else if (conversion.max && this.quantity >= conversion.max.value) {
this.unit = conversion.max.next;
this.quantity.multiply(conversion.to[this.unit]);
}
return this;
};
recipeIngredient.CONVERSIONS = {
cup: {
to: {
tablespoon: 16,
},
min: {
value: 1 / 4,
next: "tablespoon",
},
},
tablespoon: {
to: {
teaspoon: 3,
cup: 1 / 16,
},
min: {
value: 1,
next: "teaspoon",
},
max: {
value: 4,
next: "cup",
},
},
teaspoon: {
to: {
tablespoon: 1 / 3,
},
max: {
value: 3,
next: "tablespoon",
},
},
};

View File

@ -1,166 +0,0 @@
export const recipeNumber = function(number) {
const match = number.match(
/^(?:(\d+)|(?:(\d+)(?: |&nbsp;))?(?:(\d+)\/(\d+))?)$/
);
if (!match || !match[0] || match[4] == "0") {
throw `Invalid number: "${number}".`;
}
this.wholeNumber = +(match[1] || match[2]);
this.numerator = +match[3];
this.denominator = +match[4];
};
/**
* Determines if the number is a fraction.
* @this {recipeNumber}
* @return {boolean} If the number is a fraction.
*/
recipeNumber.prototype.isFraction = function() {
return !!(this.numerator && this.denominator);
};
/**
* Determines if the fraction is proper, which is defined as
* the numerator being strictly less than the denominator.
* @this {recipeNumber}
* @return {boolean} If the fraction is proper.
*/
recipeNumber.prototype.isProperFraction = function() {
return this.numerator < this.denominator;
};
/**
* Determines if the fraction is improper, which is defined as
* the numerator being greater than or equal to the denominator.
* @this {recipeNumber}
* @return {boolean} If the fraction is improper.
*/
recipeNumber.prototype.isImproperFraction = function() {
return this.numerator >= this.denominator;
};
/**
* Determines if the fraction is mixed, which is defined as
* a whole number with a proper fraction.
* @this {recipeNumber}
* @return {boolean} If the fraction is mixed.
*/
recipeNumber.prototype.isMixedFraction = function() {
return this.isProperFraction() && !isNaN(this.wholeNumber);
};
/**
* Simplifies fractions. Examples:
* 3/2 = 1 1/2
* 4/2 = 2
* 1 3/2 = 2 1/2
* 0/1 = 0
* 1 0/1 = 1
* @this {recipeNumber}
* @return {recipeNumber} The instance.
*/
recipeNumber.prototype.simplifyFraction = function() {
if (this.isImproperFraction()) {
this.wholeNumber |= 0;
this.wholeNumber += Math.floor(this.numerator / this.denominator);
const modulus = this.numerator % this.denominator;
if (modulus) {
this.numerator = modulus;
} else {
this.numerator = this.denominator = NaN;
}
} else if (this.numerator == 0) {
this.wholeNumber |= 0;
this.numerator = this.denominator = NaN;
}
return this;
};
/**
* Reduces a fraction. Examples:
* 2/6 = 1/3
* 6/2 = 3/1
* @this {recipeNumber}
* @return {recipeNumber} The instance.
*/
recipeNumber.prototype.reduceFraction = function() {
if (this.isFraction()) {
const gcd = recipeNumber.gcd(this.numerator, this.denominator);
this.numerator /= gcd;
this.denominator /= gcd;
}
return this;
};
/**
* Converts proper fractions to improper fractions. Examples:
* 1 1/2 = 3/2
* 3/2 = 3/2
* 1/2 = 1/2
* 2 = 2
*
* @this {recipeNumber}
* @return {recipeNumber} The instance.
*/
recipeNumber.prototype.toImproperFraction = function() {
if (!isNaN(this.wholeNumber)) {
this.numerator |= 0;
this.denominator = this.denominator || 1;
this.numerator += this.wholeNumber * this.denominator;
this.wholeNumber = NaN;
}
return this;
};
/**
* Multiplies the number by some decimal value.
* @param {number} multiplier The multiplier.
* @this {recipeNumber}
* @return {recipeNumber} The instance.
*/
recipeNumber.prototype.multiply = function(multiplier) {
this.toImproperFraction();
this.numerator *= multiplier;
return this.reduceFraction().simplifyFraction();
};
/**
* Gets a string representation of the number.
* @this {recipeNumber}
* @return {string} The string representation of the number.
*/
recipeNumber.prototype.toString = function() {
let number = "";
let fraction = "";
if (!isNaN(this.wholeNumber)) {
number += this.wholeNumber;
}
if (this.isFraction()) {
fraction = `${this.numerator}/${this.denominator}`;
}
if (number && fraction) {
number += ` ${fraction}`;
}
return number || fraction;
};
/**
* Gets a numeric representation of the number.
* @this {recipeNumber}
* @return {number} The numeric representation of the number.
*/
recipeNumber.prototype.valueOf = function() {
let value = this.wholeNumber || 0;
value += this.numerator / this.denominator || 0;
return value;
};
/**
* Euclid's algorithm to find the greatest common divisor of two numbers.
* @param {number} a One number.
* @param {number} b Another number.
* @return {number} The GCD of the numbers.
*/
recipeNumber.gcd = function gcd(a, b) {
return b ? recipeNumber.gcd(b, a % b) : a;
};

View File

@ -36,7 +36,6 @@ export const recipeAPI = {
async requestDetails(recipeSlug) {
const response = await apiReq.getSafe(API_ROUTES.recipesRecipeSlug(recipeSlug));
console.log(response);
return response;
},

View File

@ -1,20 +1,16 @@
import { API_ROUTES } from "./apiRoutes";
import { apiReq } from "./api-utils";
import axios from "axios";
import i18n from "@/i18n.js";
export const userAPI = {
async login(formData) {
let response = await apiReq.post(API_ROUTES.authToken, formData, null, function() {
let response = await apiReq.post(API_ROUTES.authToken, formData, null, () => {
return i18n.t("user.user-successfully-logged-in");
});
return response;
},
async refresh() {
let response = await axios.get(API_ROUTES.authRefresh).catch(function(event) {
console.log("Fetch failed", event);
});
return response.data ? response.data : false;
return apiReq.getSafe(API_ROUTES.authRefresh);
},
async allUsers() {
let response = await apiReq.get(API_ROUTES.users);
@ -29,8 +25,7 @@ export const userAPI = {
);
},
async self() {
let response = await apiReq.get(API_ROUTES.usersSelf);
return response.data;
return apiReq.getSafe(API_ROUTES.usersSelf);
},
async byID(id) {
let response = await apiReq.get(API_ROUTES.usersId(id));

View File

@ -106,9 +106,6 @@ export default {
},
watch: {
startDate(val) {
console.log(val);
},
dateDif() {
this.planDays = [];
for (let i = 0; i < this.dateDif; i++) {

View File

@ -10,12 +10,10 @@
<slot> </slot>
</v-img>
<div class="icon-slot" v-else @click="$emit('click')">
<div>
<slot> </slot>
</div>
<v-icon color="primary" class="icon-position" :size="iconSize">
{{ $globals.icons.primary }}
</v-icon>
<slot> </slot>
</div>
</template>

View File

@ -82,9 +82,6 @@ export default {
this.$set(this.editKeys, comment.id, false);
}
},
editKeys() {
console.log(this.editKeys);
},
},
methods: {
resetImage() {
@ -103,7 +100,6 @@ export default {
this.$emit(UPDATE_COMMENT_EVENT);
},
async createNewComment() {
console.log(this.slug);
await api.recipes.createComment(this.slug, { text: this.newComment });
this.$emit(NEW_COMMENT_EVENT);

View File

@ -47,6 +47,8 @@ export default {
showNutrition: this.$t("recipe.show-nutrition-values"),
showAssets: this.$t("recipe.show-assets"),
landscapeView: this.$t("recipe.landscape-view-coming-soon"),
disableComments: this.$t("recipe.disable-comments"),
disableAmount: this.$t("recipe.disable-amount"),
};
},
},

View File

@ -27,7 +27,7 @@
<Rating :value="rating" :name="name" :slug="slug" :small="true" />
<v-spacer></v-spacer>
<RecipeChips :truncate="true" :items="tags" :title="false" :limit="2" :small="true" :isCategory="false" />
<ContextMenu :slug="slug" :name="name"/>
<ContextMenu :slug="slug" :name="name" />
</v-card-actions>
</v-card>
</v-hover>

View File

@ -210,6 +210,8 @@
"calories-suffix": "calories",
"carbohydrate-content": "Carbohydrate",
"categories": "Categories",
"disable-comments": "Disable Comments",
"disable-amount": "Disable Ingredient Amounts",
"delete-confirmation": "Are you sure you want to delete this recipe?",
"delete-recipe": "Delete Recipe",
"description": "Description",

View File

@ -150,7 +150,13 @@ export default {
methods: {
async refreshProfile() {
this.user = await api.users.self();
const [response, err] = await api.users.self();
if (err) {
return; // TODO: Log or Notifty User of Error
}
this.user = response.data;
},
openAvatarPicker() {
this.showAvatarPicker = true;

View File

@ -55,6 +55,7 @@
/>
</v-card>
<CommentsSection
v-if="recipeDetails.settings && !recipeDetails.settings.disableComments"
class="mt-2 d-print-none"
:slug="recipeDetails.slug"
:comments="recipeDetails.comments"

View File

@ -199,7 +199,6 @@ export default {
},
async importIngredients(selected) {
const [response, error] = await api.recipes.requestDetails(selected.slug);
console.log(response);
if (error) {
console.log(error);

View File

@ -56,8 +56,13 @@ const mutations = {
const actions = {
async requestUserData({ getters, commit }) {
if (getters.getIsLoggedIn) {
const userData = await api.users.self();
commit("setUserData", userData);
const [response, err] = await api.users.self();
if (err) {
return; // TODO: Log or Notifty User of Error
}
commit("setUserData", response.data);
}
},
@ -76,13 +81,15 @@ const actions = {
console.log("Not Logged In");
return;
}
try {
let authResponse = await api.users.refresh();
commit("setToken", authResponse.access_token);
} catch {
const [response, err] = await api.users.refresh();
if (err) {
console.log("Failed Token Refresh, Logging Out...");
commit("setIsLoggedIn", false);
}
commit("setToken", response.data.access_token);
},
async initTheme({ dispatch, getters }) {

View File

@ -1,6 +1,6 @@
from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase
from requests import Session
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, Table, orm
from sqlalchemy import Column, ForeignKey, Integer, String, Table, orm
ingredients_to_units = Table(
"ingredients_to_units",
@ -82,14 +82,10 @@ class RecipeIngredient(SqlAlchemyBase):
quantity = Column(Integer)
# Extras
disable_amount = Column(Boolean, default=False)
def __init__(
self, title: str, note: str, unit: dict, food: dict, quantity: int, disable_amount: bool, session: Session, **_
) -> None:
def __init__(self, title: str, note: str, unit: dict, food: dict, quantity: int, session: Session, **_) -> None:
self.title = title
self.note = note
self.unit = IngredientUnit.get_ref_or_create(session, unit)
self.food = IngredientFood.get_ref_or_create(session, food)
self.quantity = quantity
self.disable_amount = disable_amount

View File

@ -10,9 +10,21 @@ class RecipeSettings(SqlAlchemyBase):
show_nutrition = sa.Column(sa.Boolean)
show_assets = sa.Column(sa.Boolean)
landscape_view = sa.Column(sa.Boolean)
disable_amount = sa.Column(sa.Boolean, default=False)
disable_comments = sa.Column(sa.Boolean, default=False)
def __init__(self, public=True, show_nutrition=True, show_assets=True, landscape_view=True) -> None:
def __init__(
self,
public=True,
show_nutrition=True,
show_assets=True,
landscape_view=True,
disable_amount=True,
disable_comments=False,
) -> None:
self.public = public
self.show_nutrition = show_nutrition
self.show_assets = show_assets
self.landscape_view = landscape_view
self.disable_amount = disable_amount
self.disable_comments = disable_comments

View File

@ -16,6 +16,8 @@ class RecipeSettings(CamelModel):
show_nutrition: bool = True
show_assets: bool = True
landscape_view: bool = True
disable_comments: bool = False
disable_amount: bool = False
class Config:
orm_mode = True