Feature/infinite scroll (#719)

* feat(frontend):  lazy-load all recipes page

* feat(frontend):  enable runtime theme through env-variables

* docs(docs): 📝 update v1 changelog

* bump version

Co-authored-by: Hayden <hay-kot@pm.me>
This commit is contained in:
Hayden 2021-10-03 14:07:18 -08:00 committed by GitHub
parent 568215cf70
commit c0dd07f9e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 548 additions and 281 deletions

View file

@ -11,9 +11,28 @@ services:
- 9091:3000
environment:
- GLOBAL_MIDDLEWARE=auth
- SUB_PATH=/mealie/
# - SUB_PATH=/mealie/
- ALLOW_SIGNUP=true
- API_URL=http://mealie-api:80
# =====================================
# Light Mode Config
- THEME_LIGHT_PRIMARY=#E58325
- THEME_LIGHT_ACCENT=#007A99
- THEME_LIGHT_SECONDARY=#973542
- THEME_LIGHT_SUCCESS=#43A047
- THEME_LIGHT_INFO=#1976D2
- THEME_LIGHT_WARNING=#FF6D00
- THEME_LIGHT_ERROR=#EF5350
# =====================================
# Light Mode Config
- THEME_DARK_PRIMARY=#E58325
- THEME_DARK_ACCENT=#007A99
- THEME_DARK_SECONDARY=#973542
- THEME_DARK_SUCCESS=#43A047
- THEME_DARK_INFO=#1976D2
- THEME_DARK_WARNING=#FF6D00
- THEME_DARK_ERROR=#EF5350
mealie:
container_name: mealie-api
build:

View file

@ -0,0 +1,47 @@
# v1.0.0 A Whole New App!
# DRAFT
!!! error "Breaking Changes"
As you may have guessed, this release comes with some breaking changes. If you are/were consuming the API you will need to validate all endpoints as nearly all of them have changed.
To import your data into Mealie v1 from the most recent previous release, you'll need to export and import your data using the bult in method. **Note that only your recipes will be usable in the migration**.
## ✨ What's New (What isn't?!?!)
### 🥳 General
- Mealie will by default only be accessible to users. Future plans are to create spaces for non-users to access a specific group.
- Mealie has gone through a big redesign and has tried to standerize it's look a feel a bit more across the board.
- User/Group settings are now completly seperated from the Administration page.
- All settings and configurations pages now have some sort of self-documenting help text. Additional text or descriptions are welcome from PRs
### 👨‍👩‍👧‍👦 Users and Groups
- Recipes are now only viewable by group members
- All memebers of a group can generate invitation tokens for other users to join their group
- Users now a have "Advaced" setting to enable/disable features like Webhooks and API tokens. This will also apply to future features that are deemed as advanced.
- "Pages" have been dropped in favor of Cookbooks which are now group specific so each group can have it's own set of cookbooks
- Default recipe settings can now be set by the group instead of environmental variables.
### 🗓 Meal Plans
- Mealplans have been completly redesigned to use a calendar approach so you'll be able to see what meals you have planned in a more traditional view
- Drag and Drop meals between days
- Add Recipes or Notes to a specific day
### 🥙 Recipes
- Foods/Units for Ingredients are now supported (toggle inside your recipe settings)
- Common Food and Units come pre-packaged with Mealie
- Recipes can now scale when Food/Units are properly defined
- Landscape and Portrait views is now available
### ⚠️ Other things to know...
- Themes have been depreciated for specific users. You can still set specific themes for your site through ENV variables. This approach should yield much better results for perforance and some weirdness users have experienced.
- If you've experienced slowness in the past, you may notice a significant improvement in the "All Recipes" and "Search" pages, or whereever large payloads of recipes are being displayed. This is due to not validating responses from the database, as such if you are consuming these API's you may get extra values that are unexpected.
### 👨‍💻 Backend/Development Goodies
- Codebase is siginficantly more organized both Frontend and Backend
- We've moved to Nuxt for SSR and Typescript for better type safety and less bugs 🎉
- Backend now using a Class based architecture to maxamize code reuse
- Tons of performance improvements across the board

View file

@ -112,35 +112,48 @@ services:
POSTGRES_USER: mealie
```
## Env Variables
## mealie-api Env Variables
| Variables | Default | Description |
| ----------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| PUID | 911 | UserID permissions between host OS and container |
| PGID | 911 | GroupID permissions between host OS and container |
| DEFAULT_GROUP | Home | The default group for users |
| DEFAULT_EMAIL | changeme@email.com | The default username for the superuser |
| BASE_URL | http://localhost:8080 | Used for Notifications |
| DB_ENGINE | sqlite | Optional: 'sqlite', 'postgres' |
| POSTGRES_USER | mealie | Postgres database user |
| POSTGRES_PASSWORD | mealie | Postgres database password |
| POSTGRES_SERVER | postgres | Postgres database server address |
| POSTGRES_PORT | 5432 | Postgres database port |
| POSTGRES_DB | mealie | Postgres database name |
| TOKEN_TIME | 2 | The time in hours that a login/auth token is valid |
| RECIPE_PUBLIC | True | Default Recipe Settings - Make Recipe Public |
| RECIPE_SHOW_NUTRITION | True | Default Recipe Settings - Show Recipe Nutrition |
| RECIPE_SHOW_ASSETS | True | Default Recipe Settings - Show Recipe Assets |
| RECIPE_LANDSCAPE_VIEW | True | Default Recipe Settings - Set Landscape View |
| RECIPE_DISABLE_COMMENTS | False | Default Recipe Settings - Disable Comments |
| RECIPE_DISABLE_AMOUNT | False | Default Recipe Settings - Disable Amount |
| API_PORT | 9000 | The port exposed by backend API. **Do not change this if you're running in Docker** |
| API_DOCS | True | Turns on/off access to the API documentation locally. |
| TZ | UTC | Must be set to get correct date/time on the server |
| WORKERS_PER_CORE | 1 | Set the number of workers to the number of CPU cores multiplied by this value (Value \* CPUs). More info [here][workers_per_core] |
| MAX_WORKERS | | Set the maximum number of workers to use. Default is not set meaning unlimited. More info [here][max_workers] |
| WEB_CONCURRENCY | 2 | Override the automatic definition of number of workers. More info [here][web_concurrency] |
| Variables | Default | Description |
| ----------------- | :-------------------: | --------------------------------------------------------------------------------------------------------------------------------- |
| PUID | 911 | UserID permissions between host OS and container |
| PGID | 911 | GroupID permissions between host OS and container |
| DEFAULT_GROUP | Home | The default group for users |
| DEFAULT_EMAIL | changeme@email.com | The default username for the superuser |
| BASE_URL | http://localhost:8080 | Used for Notifications |
| DB_ENGINE | sqlite | Optional: 'sqlite', 'postgres' |
| POSTGRES_USER | mealie | Postgres database user |
| POSTGRES_PASSWORD | mealie | Postgres database password |
| POSTGRES_SERVER | postgres | Postgres database server address |
| POSTGRES_PORT | 5432 | Postgres database port |
| POSTGRES_DB | mealie | Postgres database name |
| TOKEN_TIME | 2 | The time in hours that a login/auth token is valid |
| API_PORT | 9000 | The port exposed by backend API. **Do not change this if you're running in Docker** |
| API_DOCS | True | Turns on/off access to the API documentation locally. |
| TZ | UTC | Must be set to get correct date/time on the server |
| WORKERS_PER_CORE | 1 | Set the number of workers to the number of CPU cores multiplied by this value (Value \* CPUs). More info [here][workers_per_core] |
| MAX_WORKERS | | Set the maximum number of workers to use. Default is not set meaning unlimited. More info [here][max_workers] |
| WEB_CONCURRENCY | 2 | Override the automatic definition of number of workers. More info [here][web_concurrency] |
## mealie-frontend Env Variables
| Variables | Default | Description |
| --------------------- | :-----: | ---------------------------------- |
| ALLOW_SIGNUP | true | Allows anyone to signup for Mealie |
| THEME_LIGHT_PRIMARY | #E58325 | Light Theme Config Variable |
| THEME_LIGHT_ACCENT | #007A99 | Light Theme Config Variable |
| THEME_LIGHT_SECONDARY | #973542 | Light Theme Config Variable |
| THEME_LIGHT_SUCCESS | #43A047 | Light Theme Config Variable |
| THEME_LIGHT_INFO | #1976D2 | Light Theme Config Variable |
| THEME_LIGHT_WARNING | #FF6D00 | Light Theme Config Variable |
| THEME_LIGHT_ERROR | #EF5350 | Light Theme Config Variable |
| DARK_LIGHT_PRIMARY | #E58325 | Dark Theme Config Variable |
| DARK_LIGHT_ACCENT | #007A99 | Dark Theme Config Variable |
| DARK_LIGHT_SECONDARY | #973542 | Dark Theme Config Variable |
| DARK_LIGHT_SUCCESS | #43A047 | Dark Theme Config Variable |
| DARK_LIGHT_INFO | #1976D2 | Dark Theme Config Variable |
| DARK_LIGHT_WARNING | #FF6D00 | Dark Theme Config Variable |
| DARK_LIGHT_ERROR | #EF5350 | Dark Theme Config Variable |
## Raspberry Pi 4

File diff suppressed because one or more lines are too long

View file

@ -94,6 +94,7 @@ nav:
- Style Guide: "contributors/developers-guide/style-guide.md"
- Development Road Map: "roadmap.md"
- Change Log:
- v1.0.0 A Whole New App: "changelog/v1.0.0.md"
- v0.5.2 Misc Updates: "changelog/v0.5.2.md"
- v0.5.1 Bug Fixes: "changelog/v0.5.1.md"
- v0.5.0 General Upgrades: "changelog/v0.5.0.md"

View file

@ -57,7 +57,7 @@
</v-app-bar>
<div v-if="recipes" class="mt-2">
<v-row v-if="!viewScale">
<v-col v-for="recipe in recipes" :key="recipe.name" :sm="6" :md="6" :lg="4" :xl="3">
<v-col v-for="(recipe, index) in recipes" :key="recipe.slug + index" :sm="6" :md="6" :lg="4" :xl="3">
<v-lazy>
<RecipeCard
:name="recipe.name"
@ -72,7 +72,7 @@
</v-row>
<v-row v-else dense>
<v-col
v-for="recipe in recipes.slice(0, cardLimit)"
v-for="recipe in recipes"
:key="recipe.name"
cols="12"
:sm="singleColumn ? '12' : '12'"
@ -93,11 +93,6 @@
</v-col>
</v-row>
</div>
<div v-intersect="bumpList" class="d-flex mt-5">
<v-fade-transition>
<AppLoader v-if="loading" :loading="loading" />
</v-fade-transition>
</div>
</div>
</template>
@ -150,7 +145,6 @@ export default {
data() {
return {
sortLoading: false,
cardLimit: 50,
loading: false,
EVENTS: {
az: "az",
@ -180,21 +174,8 @@ export default {
return this.icon || this.$globals.icons.tags;
},
},
watch: {
recipes() {
this.bumpList();
},
},
methods: {
bumpList() {
const newCardLimit = Math.min(this.cardLimit + 20, this.effectiveHardLimit);
if (this.loading === false && newCardLimit > this.cardLimit) {
this.setLoader();
}
this.cardLimit = newCardLimit;
},
async setLoader() {
this.loading = true;
// eslint-disable-next-line promise/param-names
@ -202,7 +183,7 @@ export default {
this.loading = false;
},
navigateRandom() {
const recipe = this.utils.recipe.randomRecipe(this.recipes);
const recipe = this.recipes[Math.floor(Math.random() * this.recipes.length)];
this.$router.push(`/recipe/${recipe.slug}`);
},
sortRecipes(sortType) {

View file

@ -18,7 +18,6 @@ export default defineComponent({
},
setup() {
const [state, toggle] = useToggle();
console.log(state, toggle);
return {
state,
toggle,

View file

@ -57,6 +57,26 @@ export const useSorter = () => {
};
};
export const useLazyRecipes = function () {
const api = useApiSingleton();
const recipes = ref<Recipe[] | null>([]);
async function fetchMore(start: number, limit: number) {
const { data } = await api.recipes.getAll(start, limit);
if (data) {
data.forEach((recipe) => {
recipes.value?.push(recipe);
});
}
}
return {
recipes,
fetchMore,
};
};
export const useRecipes = (all = false, fetchRecipes = true) => {
const api = useApiSingleton();

View file

@ -30,7 +30,7 @@ export default {
css: [{ src: "~/assets/main.css" }, { src: "~/assets/style-overrides.scss" }],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: ["~/plugins/globals.ts"],
plugins: ["~/plugins/globals.ts", "~/plugins/theme.ts"],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
@ -205,6 +205,26 @@ export default {
axios: {
browserBaseURL: process.env.SUB_PATH || "",
},
themes: {
dark: {
primary: process.env.THEME_DARK_PRIMARY || "#E58325",
accent: process.env.THEME_DARK_ACCENT || "#007A99",
secondary: process.env.THEME_DARK_SECONDARY || "#973542",
success: process.env.THEME_DARK_SUCCESS || "#43A047",
info: process.env.THEME_DARK_INFO || "#1976d2",
warning: process.env.THEME_DARK_WARNING || "#FF6D00",
error: process.env.THEME_DARK_ERROR || "#EF5350",
},
light: {
primary: process.env.THEME_LIGHT_PRIMARY || "#007A99",
accent: process.env.THEME_LIGHT_ACCENT || "#007A99",
secondary: process.env.THEME_DARK_SECONDARY || "#973542",
success: process.env.THEME_DARK_SUCCESS || "#43A047",
info: process.env.THEME_LIGHT_INFO || "#1976d2",
warning: process.env.THEME_LIGHT_WARNING || "#FF6D00",
error: process.env.THEME_LIGHT_ERROR || "#EF5350",
},
},
},
privateRuntimeConfig: {},
@ -249,6 +269,8 @@ export default {
customProperties: true,
},
dark: false,
// Theme Config set at runtime by /plugins/theme.ts
// This config doesn't do anything.
themes: {
dark: {
primary: "#E58325",

View file

@ -3,23 +3,49 @@
<RecipeCardSection
:icon="$globals.icons.primary"
:title="$t('page.all-recipes')"
:recipes="allRecipes"
@sort="assignSorted"
:recipes="recipes"
></RecipeCardSection>
<v-card v-intersect="infiniteScroll"></v-card>
<v-fade-transition>
<AppLoader v-if="loading" :loading="loading" />
</v-fade-transition>
</v-container>
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api";
import { defineComponent, onMounted, ref } from "@nuxtjs/composition-api";
import { useThrottleFn } from "@vueuse/core";
import RecipeCardSection from "~/components/Domain/Recipe/RecipeCardSection.vue";
import { useRecipes, allRecipes } from "~/composables/use-recipes";
import { useLazyRecipes } from "~/composables/use-recipes";
export default defineComponent({
components: { RecipeCardSection },
setup() {
const { assignSorted } = useRecipes(true);
const start = ref(1);
const limit = ref(30);
const increment = ref(30);
const ready = ref(false);
const loading = ref(false);
return { allRecipes, assignSorted };
const { recipes, fetchMore } = useLazyRecipes();
onMounted(async () => {
await fetchMore(start.value, limit.value);
ready.value = true;
});
const infiniteScroll = useThrottleFn(() => {
if (!ready.value) {
return;
}
loading.value = true;
start.value = limit.value + 1;
limit.value = limit.value + increment.value;
fetchMore(start.value, limit.value);
loading.value = false;
}, 500);
return { recipes, infiniteScroll, loading };
},
});
</script>

View file

@ -58,8 +58,7 @@
<RecipeCardSection
class="mt-n5"
:title-icon="$globals.icons.magnify"
:recipes="showRecipes"
:hard-limit="maxResults"
:recipes="showRecipes.slice(0, maxResults)"
@sort="assignFuzzy"
/>
</v-container>

View file

@ -1,214 +1,4 @@
import {
mdiAccount,
mdiSilverwareVariant,
mdiPlus,
mdiPlusCircle,
mdiDelete,
mdiContentSave,
mdiContentSaveEdit,
mdiSquareEditOutline,
mdiClose,
mdiTagMultipleOutline,
mdiBookOutline,
mdiAccountCog,
mdiAccountGroup,
mdiHome,
mdiMagnify,
mdiTranslate,
mdiClockTimeFourOutline,
mdiImport,
mdiEmail,
mdiLock,
mdiEye,
mdiDrag,
mdiEyeOff,
mdiCalendarMinus,
mdiCalendar,
mdiDiceMultiple,
mdiAlertCircle,
mdiDotsVertical,
mdiPrinter,
mdiShareVariant,
mdiHeart,
mdiHeartOutline,
mdiDotsHorizontal,
mdiCheckboxBlankOutline,
mdiCommentTextMultipleOutline,
mdiDownload,
mdiFile,
mdiFilePdfBox,
mdiFileImage,
mdiCodeJson,
mdiCog,
mdiSort,
mdiOrderAlphabeticalAscending,
mdiStar,
mdiNewBox,
mdiShuffleVariant,
mdiAlert,
mdiCheckboxMarkedCircle,
mdiInformation,
mdiBellAlert,
mdiRefreshCircle,
mdiMenu,
mdiWeatherSunny,
mdiWeatherNight,
mdiLink,
mdiRobot,
mdiLinkVariant,
mdiViewModule,
mdiViewDashboard,
mdiTools,
mdiCalendarWeek,
mdiCalendarToday,
mdiCalendarMultiselect,
mdiFormatListChecks,
mdiLogout,
mdiContentCopy,
mdiClipboardCheck,
mdiCloudUpload,
mdiDatabase,
mdiGithub,
mdiFolderOutline,
mdiApi,
mdiTestTube,
mdiDevTo,
mdiBackupRestore,
mdiNotificationClearAll,
mdiFood,
mdiWebhook,
mdiFilter,
mdiAccountPlusOutline,
mdiDesktopTowerMonitor,
mdiFormatColorFill,
mdiFormSelect,
mdiPageLayoutBody,
mdiCalendarWeekBegin,
mdiOpenInNew,
mdiCheck,
mdiBroom,
mdiCartCheck,
mdiArrowLeftBold,
mdiMinus,
mdiWindowClose,
mdiFolderZipOutline,
mdiFoodApple,
mdiBeakerOutline,
mdiArrowLeftBoldOutline,
mdiArrowRightBoldOutline,
} from "@mdi/js";
const icons = {
// Primary
primary: mdiSilverwareVariant,
// General
foods: mdiFoodApple,
units: mdiBeakerOutline,
alert: mdiAlert,
alertCircle: mdiAlertCircle,
api: mdiApi,
arrowLeftBold: mdiArrowLeftBold,
arrowUpDown: mdiDrag,
backupRestore: mdiBackupRestore,
bellAlert: mdiBellAlert,
broom: mdiBroom,
calendar: mdiCalendar,
calendarMinus: mdiCalendarMinus,
calendarMultiselect: mdiCalendarMultiselect,
calendarToday: mdiCalendarToday,
calendarWeek: mdiCalendarWeek,
calendarWeekBegin: mdiCalendarWeekBegin,
cartCheck: mdiCartCheck,
check: mdiCheck,
checkboxBlankOutline: mdiCheckboxBlankOutline,
checkboxMarkedCircle: mdiCheckboxMarkedCircle,
clipboardCheck: mdiClipboardCheck,
clockOutline: mdiClockTimeFourOutline,
codeBraces: mdiCodeJson,
codeJson: mdiCodeJson,
cog: mdiCog,
commentTextMultipleOutline: mdiCommentTextMultipleOutline,
contentCopy: mdiContentCopy,
database: mdiDatabase,
desktopTowerMonitor: mdiDesktopTowerMonitor,
devTo: mdiDevTo,
diceMultiple: mdiDiceMultiple,
dotsHorizontal: mdiDotsHorizontal,
dotsVertical: mdiDotsVertical,
download: mdiDownload,
email: mdiEmail,
externalLink: mdiLinkVariant,
eye: mdiEye,
eyeOff: mdiEyeOff,
file: mdiFile,
fileImage: mdiFileImage,
filePDF: mdiFilePdfBox,
filter: mdiFilter,
folderOutline: mdiFolderOutline,
food: mdiFood,
formatColorFill: mdiFormatColorFill,
formatListCheck: mdiFormatListChecks,
formSelect: mdiFormSelect,
github: mdiGithub,
heart: mdiHeart,
heartOutline: mdiHeartOutline,
home: mdiHome,
import: mdiImport,
information: mdiInformation,
link: mdiLink,
lock: mdiLock,
logout: mdiLogout,
menu: mdiMenu,
newBox: mdiNewBox,
notificationClearAll: mdiNotificationClearAll,
openInNew: mdiOpenInNew,
orderAlphabeticalAscending: mdiOrderAlphabeticalAscending,
pageLayoutBody: mdiPageLayoutBody,
printer: mdiPrinter,
refreshCircle: mdiRefreshCircle,
robot: mdiRobot,
search: mdiMagnify,
shareVariant: mdiShareVariant,
shuffleVariant: mdiShuffleVariant,
sort: mdiSort,
star: mdiStar,
testTube: mdiTestTube,
tools: mdiTools,
translate: mdiTranslate,
upload: mdiCloudUpload,
viewDashboard: mdiViewDashboard,
viewModule: mdiViewModule,
weatherNight: mdiWeatherNight,
weatherSunny: mdiWeatherSunny,
webhook: mdiWebhook,
windowClose: mdiWindowClose,
zip: mdiFolderZipOutline,
// Crud
backArrow: mdiArrowLeftBoldOutline,
createAlt: mdiPlus,
create: mdiPlusCircle,
delete: mdiDelete,
save: mdiContentSave,
update: mdiContentSaveEdit,
edit: mdiSquareEditOutline,
close: mdiClose,
minus: mdiMinus,
// Organization
tags: mdiTagMultipleOutline,
pages: mdiBookOutline,
// Admin
user: mdiAccount,
admin: mdiAccountCog,
group: mdiAccountGroup,
accountPlusOutline: mdiAccountPlusOutline,
forward: mdiArrowRightBoldOutline,
back: mdiArrowLeftBoldOutline,
};
import { icons } from "~/utils/icons";
// eslint-disable-next-line no-empty-pattern
export default ({}, inject: any) => {

View file

@ -0,0 +1,3 @@
export default ({ $vuetify, $config }: any) => {
$vuetify.theme.themes = $config.themes;
};

View file

@ -1,3 +1,22 @@
GLOBAL_MIDDLEWARE=null # null or 'auth'
GLOBAL_MIDDLEWARE=null
BASE_URL = ""
ALLOW_SIGNUP=true
ALLOW_SIGNUP=true
# =====================================
# Light Mode Config
THEME_LIGHT_PRIMARY=#007A99
THEME_LIGHT_ACCENT=#007A99
THEME_LIGHT_SECONDARY=#973542
THEME_LIGHT_SUCCESS=#43A047
THEME_LIGHT_INFO=#1976D2
THEME_LIGHT_WARNING=#FF6D00
THEME_LIGHT_ERROR=#EF5350
# =====================================
# Light Mode Config
THEME_DARK_PRIMARY=#E58325
THEME_DARK_ACCENT=#007A99
THEME_DARK_SECONDARY=#973542
THEME_DARK_SUCCESS=#43A047
THEME_DARK_INFO=#1976D2
THEME_DARK_WARNING=#FF6D00
THEME_DARK_ERROR=#EF5350

View file

@ -1,5 +1,10 @@
import Vue from "vue";
import "@nuxt/types";
import { Icon } from "~/utils/icons/icon-type";
interface Globals {
icons: Icon;
}
declare module "vue/types/vue" {
interface Vue {
@ -9,9 +14,9 @@ declare module "vue/types/vue" {
declare module "vue/types/options" {
interface ComponentOptions<V extends Vue> {
$globals?: any;
$globals?: Globals;
}
interface ComponentOptions<V extends UseContextReturn> {
$globals?: any;
$globals?: Globals;
}
}

View file

@ -0,0 +1,111 @@
export interface Icon {
// Primary
primary: String;
// General
foods: String;
units: String;
alert: String;
alertCircle: String;
api: String;
arrowLeftBold: String;
arrowUpDown: String;
backupRestore: String;
bellAlert: String;
broom: String;
calendar: String;
calendarMinus: String;
calendarMultiselect: String;
calendarToday: String;
calendarWeek: String;
calendarWeekBegin: String;
cartCheck: String;
check: String;
checkboxBlankOutline: String;
checkboxMarkedCircle: String;
clipboardCheck: String;
clockOutline: String;
codeBraces: String;
codeJson: String;
cog: String;
commentTextMultipleOutline: String;
contentCopy: String;
database: String;
desktopTowerMonitor: String;
devTo: String;
diceMultiple: String;
dotsHorizontal: String;
dotsVertical: String;
download: String;
email: String;
externalLink: String;
eye: String;
eyeOff: String;
file: String;
fileImage: String;
filePDF: String;
filter: String;
folderOutline: String;
food: String;
formatColorFill: String;
formatListCheck: String;
formSelect: String;
github: String;
heart: String;
heartOutline: String;
home: String;
import: String;
information: String;
link: String;
lock: String;
logout: String;
menu: String;
newBox: String;
notificationClearAll: String;
openInNew: String;
orderAlphabeticalAscending: String;
pageLayoutBody: String;
printer: String;
refreshCircle: String;
robot: String;
search: String;
shareVariant: String;
shuffleVariant: String;
sort: String;
star: String;
testTube: String;
tools: String;
translate: String;
upload: String;
viewDashboard: String;
viewModule: String;
weatherNight: String;
weatherSunny: String;
webhook: String;
windowClose: String;
zip: String;
// Crud
backArrow: String;
createAlt: String;
create: String;
delete: String;
save: String;
update: String;
edit: String;
close: String;
minus: String;
// Organization
tags: String;
pages: String;
// Admin
user: String;
admin: String;
group: String;
accountPlusOutline: String;
forward: String;
back: String;
}

View file

@ -0,0 +1,211 @@
import {
mdiAccount,
mdiSilverwareVariant,
mdiPlus,
mdiPlusCircle,
mdiDelete,
mdiContentSave,
mdiContentSaveEdit,
mdiSquareEditOutline,
mdiClose,
mdiTagMultipleOutline,
mdiBookOutline,
mdiAccountCog,
mdiAccountGroup,
mdiHome,
mdiMagnify,
mdiTranslate,
mdiClockTimeFourOutline,
mdiImport,
mdiEmail,
mdiLock,
mdiEye,
mdiDrag,
mdiEyeOff,
mdiCalendarMinus,
mdiCalendar,
mdiDiceMultiple,
mdiAlertCircle,
mdiDotsVertical,
mdiPrinter,
mdiShareVariant,
mdiHeart,
mdiHeartOutline,
mdiDotsHorizontal,
mdiCheckboxBlankOutline,
mdiCommentTextMultipleOutline,
mdiDownload,
mdiFile,
mdiFilePdfBox,
mdiFileImage,
mdiCodeJson,
mdiCog,
mdiSort,
mdiOrderAlphabeticalAscending,
mdiStar,
mdiNewBox,
mdiShuffleVariant,
mdiAlert,
mdiCheckboxMarkedCircle,
mdiInformation,
mdiBellAlert,
mdiRefreshCircle,
mdiMenu,
mdiWeatherSunny,
mdiWeatherNight,
mdiLink,
mdiRobot,
mdiLinkVariant,
mdiViewModule,
mdiViewDashboard,
mdiTools,
mdiCalendarWeek,
mdiCalendarToday,
mdiCalendarMultiselect,
mdiFormatListChecks,
mdiLogout,
mdiContentCopy,
mdiClipboardCheck,
mdiCloudUpload,
mdiDatabase,
mdiGithub,
mdiFolderOutline,
mdiApi,
mdiTestTube,
mdiDevTo,
mdiBackupRestore,
mdiNotificationClearAll,
mdiFood,
mdiWebhook,
mdiFilter,
mdiAccountPlusOutline,
mdiDesktopTowerMonitor,
mdiFormatColorFill,
mdiFormSelect,
mdiPageLayoutBody,
mdiCalendarWeekBegin,
mdiOpenInNew,
mdiCheck,
mdiBroom,
mdiCartCheck,
mdiArrowLeftBold,
mdiMinus,
mdiWindowClose,
mdiFolderZipOutline,
mdiFoodApple,
mdiBeakerOutline,
mdiArrowLeftBoldOutline,
mdiArrowRightBoldOutline,
} from "@mdi/js";
export const icons = {
// Primary
primary: mdiSilverwareVariant,
// General
foods: mdiFoodApple,
units: mdiBeakerOutline,
alert: mdiAlert,
alertCircle: mdiAlertCircle,
api: mdiApi,
arrowLeftBold: mdiArrowLeftBold,
arrowUpDown: mdiDrag,
backupRestore: mdiBackupRestore,
bellAlert: mdiBellAlert,
broom: mdiBroom,
calendar: mdiCalendar,
calendarMinus: mdiCalendarMinus,
calendarMultiselect: mdiCalendarMultiselect,
calendarToday: mdiCalendarToday,
calendarWeek: mdiCalendarWeek,
calendarWeekBegin: mdiCalendarWeekBegin,
cartCheck: mdiCartCheck,
check: mdiCheck,
checkboxBlankOutline: mdiCheckboxBlankOutline,
checkboxMarkedCircle: mdiCheckboxMarkedCircle,
clipboardCheck: mdiClipboardCheck,
clockOutline: mdiClockTimeFourOutline,
codeBraces: mdiCodeJson,
codeJson: mdiCodeJson,
cog: mdiCog,
commentTextMultipleOutline: mdiCommentTextMultipleOutline,
contentCopy: mdiContentCopy,
database: mdiDatabase,
desktopTowerMonitor: mdiDesktopTowerMonitor,
devTo: mdiDevTo,
diceMultiple: mdiDiceMultiple,
dotsHorizontal: mdiDotsHorizontal,
dotsVertical: mdiDotsVertical,
download: mdiDownload,
email: mdiEmail,
externalLink: mdiLinkVariant,
eye: mdiEye,
eyeOff: mdiEyeOff,
file: mdiFile,
fileImage: mdiFileImage,
filePDF: mdiFilePdfBox,
filter: mdiFilter,
folderOutline: mdiFolderOutline,
food: mdiFood,
formatColorFill: mdiFormatColorFill,
formatListCheck: mdiFormatListChecks,
formSelect: mdiFormSelect,
github: mdiGithub,
heart: mdiHeart,
heartOutline: mdiHeartOutline,
home: mdiHome,
import: mdiImport,
information: mdiInformation,
link: mdiLink,
lock: mdiLock,
logout: mdiLogout,
menu: mdiMenu,
newBox: mdiNewBox,
notificationClearAll: mdiNotificationClearAll,
openInNew: mdiOpenInNew,
orderAlphabeticalAscending: mdiOrderAlphabeticalAscending,
pageLayoutBody: mdiPageLayoutBody,
printer: mdiPrinter,
refreshCircle: mdiRefreshCircle,
robot: mdiRobot,
search: mdiMagnify,
shareVariant: mdiShareVariant,
shuffleVariant: mdiShuffleVariant,
sort: mdiSort,
star: mdiStar,
testTube: mdiTestTube,
tools: mdiTools,
translate: mdiTranslate,
upload: mdiCloudUpload,
viewDashboard: mdiViewDashboard,
viewModule: mdiViewModule,
weatherNight: mdiWeatherNight,
weatherSunny: mdiWeatherSunny,
webhook: mdiWebhook,
windowClose: mdiWindowClose,
zip: mdiFolderZipOutline,
// Crud
backArrow: mdiArrowLeftBoldOutline,
createAlt: mdiPlus,
create: mdiPlusCircle,
delete: mdiDelete,
save: mdiContentSave,
update: mdiContentSaveEdit,
edit: mdiSquareEditOutline,
close: mdiClose,
minus: mdiMinus,
// Organization
tags: mdiTagMultipleOutline,
pages: mdiBookOutline,
// Admin
user: mdiAccount,
admin: mdiAccountCog,
group: mdiAccountGroup,
accountPlusOutline: mdiAccountPlusOutline,
forward: mdiArrowRightBoldOutline,
back: mdiArrowLeftBoldOutline,
};

View file

@ -0,0 +1 @@
export { icons } from "./icons";

View file

@ -7,8 +7,8 @@ from typing import Any, Optional, Union
import dotenv
from pydantic import BaseSettings, Field, PostgresDsn, validator
APP_VERSION = "v0.5.2"
DB_VERSION = "v0.5.0"
APP_VERSION = "v1.0.0b"
DB_VERSION = "v1.0.0b"
CWD = Path(__file__).parent
BASE_DIR = CWD.parent.parent

View file

@ -1,6 +1,6 @@
[tool.poetry]
name = "mealie"
version = "0.5.2"
version = "1.0.0b"
description = "A Recipe Manager"
authors = ["Hayden <hay-kot@pm.me>"]
license = "MIT"

View file

@ -52,7 +52,7 @@ def test_non_default_settings(monkeypatch):
def test_default_connection_args(monkeypatch):
monkeypatch.setenv("DB_ENGINE", "sqlite")
app_settings = AppSettings()
assert re.match(r"sqlite:////.*mealie/dev/data/mealie_v0.5.0.db", app_settings.DB_URL)
assert re.match(r"sqlite:////.*mealie/dev/data/mealie_v1.0.0b.db", app_settings.DB_URL)
def test_pg_connection_args(monkeypatch):