Docs/v0.5.0 second pass (#496)
* update docs * use auto-gen routes * dumb deps * remove whitespace * github action to build dev docs container * no cache Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
parent
06ed377c00
commit
e34079673c
42 changed files with 555 additions and 508 deletions
22
.github/workflows/dockerbuild.dev.yml
vendored
22
.github/workflows/dockerbuild.dev.yml
vendored
|
@ -6,6 +6,28 @@ on:
|
|||
- dev
|
||||
|
||||
jobs:
|
||||
push_to_registry:
|
||||
name: Push Docker image to GitHub Packages
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Log in to GitHub Docker Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: docker.pkg.github.com
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build container image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
tags: |
|
||||
context: ./docs
|
||||
docker.pkg.github.com/${{ github.repository }}/dev-docs:latest
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
|
24
.gitignore
vendored
24
.gitignore
vendored
|
@ -6,7 +6,7 @@
|
|||
|
||||
# frontend/.env.development
|
||||
docs/site/
|
||||
*temp*
|
||||
*temp/*
|
||||
.secret
|
||||
|
||||
dev/data/backups/*
|
||||
|
@ -147,24 +147,4 @@ dev/data/backups/dev_sample_data*.zip
|
|||
!dev/data/backups/test*.zip
|
||||
dev/data/recipes/*
|
||||
dev/scripts/output/app_routes.py
|
||||
dev/scripts/output/javascriptAPI/apiRoutes.js
|
||||
dev/scripts/output/javascriptAPI/appEvents.js
|
||||
dev/scripts/output/javascriptAPI/authentication.js
|
||||
dev/scripts/output/javascriptAPI/backups.js
|
||||
dev/scripts/output/javascriptAPI/debug.js
|
||||
dev/scripts/output/javascriptAPI/groups.js
|
||||
dev/scripts/output/javascriptAPI/index.js
|
||||
dev/scripts/output/javascriptAPI/mealPlan.js
|
||||
dev/scripts/output/javascriptAPI/migration.js
|
||||
dev/scripts/output/javascriptAPI/queryAllRecipes.js
|
||||
dev/scripts/output/javascriptAPI/recipeCategories.js
|
||||
dev/scripts/output/javascriptAPI/recipeCRUD.js
|
||||
dev/scripts/output/javascriptAPI/recipeTags.js
|
||||
dev/scripts/output/javascriptAPI/settings.js
|
||||
dev/scripts/output/javascriptAPI/shoppingLists.js
|
||||
dev/scripts/output/javascriptAPI/siteMedia.js
|
||||
dev/scripts/output/javascriptAPI/themes.js
|
||||
dev/scripts/output/javascriptAPI/userAPITokens.js
|
||||
dev/scripts/output/javascriptAPI/users.js
|
||||
dev/scripts/output/javascriptAPI/userSignup.js
|
||||
dev/scripts/output/javascriptAPI/utils.js
|
||||
dev/scripts/output/javascriptAPI/*
|
|
@ -2,8 +2,32 @@
|
|||
admin off
|
||||
}
|
||||
|
||||
# Add gzip compression to requests
|
||||
(webconf) {
|
||||
encode gzip
|
||||
}
|
||||
|
||||
# Add forward headers to requests
|
||||
(theheaders) {
|
||||
header_up X-Forwarded-Ssl on
|
||||
header_up Host {host}
|
||||
header_up X-Real-IP {remote}
|
||||
header_up X-Forwarded-For {remote}
|
||||
header_up X-Forwarded-Port {server_port}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
header_up X-Url-Scheme {scheme}
|
||||
header_up X-Forwarded-Host {host}
|
||||
}
|
||||
|
||||
localhost {
|
||||
handle /mealie/* {
|
||||
reverse_proxy http://127.0.0.1:9090
|
||||
log
|
||||
redir /dev-docs /dev-docs/
|
||||
route /dev-docs* {
|
||||
|
||||
uri strip_prefix dev-docs
|
||||
reverse_proxy localhost:8888 {
|
||||
import theheaders
|
||||
}
|
||||
import webconf
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ class AppRoutes:
|
|||
self.recipes_summary_uncategorized = "/api/recipes/summary/uncategorized"
|
||||
self.recipes_summary_untagged = "/api/recipes/summary/untagged"
|
||||
self.recipes_tag = "/api/recipes/tag"
|
||||
self.recipes_test_scrape_url = "/api/recipes/test-scrape-url"
|
||||
self.shopping_lists = "/api/shopping-lists"
|
||||
self.site_settings = "/api/site-settings"
|
||||
self.site_settings_custom_pages = "/api/site-settings/custom-pages"
|
||||
|
|
7
dev/scripts/templates/js_index.j2
Normal file
7
dev/scripts/templates/js_index.j2
Normal file
|
@ -0,0 +1,7 @@
|
|||
{% for api in files.files %}
|
||||
import { {{ api }}API } from "./{{api}}.js" {% endfor %}
|
||||
|
||||
export const api = {
|
||||
{% for api in files.files %}
|
||||
{{api}}: {{api}}API, {% endfor %}
|
||||
}
|
19
dev/scripts/templates/js_requests.j2
Normal file
19
dev/scripts/templates/js_requests.j2
Normal file
|
@ -0,0 +1,19 @@
|
|||
// This Content is Auto Generated
|
||||
import { API_ROUTES } from "./apiRoutes"
|
||||
|
||||
export const {{paths.export_name}}API = { {% for path in paths.all_paths %} {% for verb in path.http_verbs %} {% if path.route_object.is_function %}
|
||||
/** {{ verb.js_docs }} {% for v in path.route_object.var %}
|
||||
* @param {{ v }} {% endfor %}
|
||||
*/
|
||||
{{ verb.summary_camel }}({{path.route_object.var|join(", ")}}) {
|
||||
const response = await apiReq.{{ verb.request_type.value }}(API_ROUTES.{{ path.route_object.router_camel }}({{path.route_object.var|join(", ")}}))
|
||||
return response.data
|
||||
}, {% else %}
|
||||
/** {{ verb.js_docs }} {% for v in path.route_object.var %}
|
||||
* @param {{ v }} {% endfor %}
|
||||
*/
|
||||
{{ verb.summary_camel }}() {
|
||||
const response = await apiReq.{{ verb.request_type.value }}(API_ROUTES.{{ path.route_object.router_camel }})
|
||||
return response.data
|
||||
},{% endif %} {% endfor %} {% endfor %}
|
||||
}
|
7
dev/scripts/templates/js_routes.j2
Normal file
7
dev/scripts/templates/js_routes.j2
Normal file
|
@ -0,0 +1,7 @@
|
|||
// This Content is Auto Generated
|
||||
const prefix = '{{paths.prefix}}'
|
||||
export const API_ROUTES = { {% for path in paths.static_paths %}
|
||||
{{ path.router_camel }}: `${prefix}{{ path.route }}`,{% endfor %}
|
||||
{% for path in paths.function_paths %}
|
||||
{{path.router_camel}}: ({{path.var|join(", ")}}) => `${prefix}{{ path.js_route }}`,{% endfor %}
|
||||
}
|
12
dev/scripts/templates/pytest_routes.j2
Normal file
12
dev/scripts/templates/pytest_routes.j2
Normal file
|
@ -0,0 +1,12 @@
|
|||
# This Content is Auto Generated for Pytest
|
||||
|
||||
|
||||
class AppRoutes:
|
||||
def __init__(self) -> None:
|
||||
self.prefix = '{{paths.prefix}}'
|
||||
{% for path in paths.static_paths %}
|
||||
self.{{ path.router_slug }} = "{{path.prefix}}{{ path.route }}"{% endfor %}
|
||||
{% for path in paths.function_paths %}
|
||||
def {{path.router_slug}}(self, {{path.var|join(", ")}}):
|
||||
return f"{self.prefix}{{ path.route }}"
|
||||
{% endfor %}
|
15
docs/Caddyfile
Normal file
15
docs/Caddyfile
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
auto_https off
|
||||
}
|
||||
|
||||
:80 {
|
||||
root * /srv
|
||||
encode gzip
|
||||
uri strip_suffix /
|
||||
|
||||
handle {
|
||||
try_files {path} {path}/ /index.html
|
||||
file_server
|
||||
}
|
||||
|
||||
}
|
10
docs/Dockerfile
Normal file
10
docs/Dockerfile
Normal file
|
@ -0,0 +1,10 @@
|
|||
FROM python:3.8-slim as build-stage
|
||||
WORKDIR /app
|
||||
RUN pip install --no-cache-dir mkdocs mkdocs-material
|
||||
COPY . .
|
||||
RUN mkdocs build
|
||||
|
||||
FROM caddy:alpine
|
||||
WORKDIR /app
|
||||
COPY ./Caddyfile /etc/caddy/Caddyfile
|
||||
COPY --from=build-stage /app/site /srv
|
11
docs/docker-compose.yml
Normal file
11
docs/docker-compose.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
version: "3"
|
||||
services:
|
||||
wiki:
|
||||
container_name: mealie-docs
|
||||
image: mealie-docs
|
||||
ports:
|
||||
- 8888:80
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: always
|
BIN
docs/docs/assets/img/api-key-image-v1.webp
Normal file
BIN
docs/docs/assets/img/api-key-image-v1.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
|
@ -17,11 +17,24 @@
|
|||
#### API Usage
|
||||
If you have been using the API directly, many of the routes and status codes have changed. You may experience issues with directly consuming the API.
|
||||
|
||||
#### Arm/v7 Support
|
||||
Mealie will no longer build in CI/CD due to a issue with the rust compiler on 32 bit devices. You can reference [this issue on the matrix-org/synapse](https://github.com/matrix-org/synapse/issues/9403) Github page that are facing a similar issue. You may still be able to build the docker image you-self.
|
||||
|
||||
## Bug Fixes
|
||||
- Fixed #25 - Allow changing rating without going into edit
|
||||
- Fixed #475 - trim whitespace on login
|
||||
- Fixes #435 - Better Email Regex
|
||||
- Fixed #428 - Meal Planner now works on iOS devices
|
||||
- Fixed #419 - Typos
|
||||
- Fixed #418 - You can now "export" shopping lists
|
||||
- Fixed #356 - Shopping List items are now grouped
|
||||
- Fixed #329 - Fixed profile image not loading
|
||||
- Fixed #461 - Proper JSON serialization on webhooks
|
||||
- Fixed #332 - Language settings are saved for one browser
|
||||
- Fixes #281 - Slow Handling of Large Sets of Recipes
|
||||
- Fixed #356 - Shopping lists generate duplicate items
|
||||
- Fixed #271 - Slow handling of larger data sets
|
||||
- Fixed #472, #469, #458, #456 - Improve Recipe Parser
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
|
@ -34,9 +47,12 @@
|
|||
- ⚠️ last_recipe.json is now depreciated
|
||||
- Beta Support for Postgres! 🎉 See the getting started page for details
|
||||
- Recipe Features
|
||||
- Step Sections
|
||||
- New button bar for editors with improved accessibility and performance
|
||||
- Step Sections now supported
|
||||
- Recipe Assets
|
||||
- Add Asset image to recipe step
|
||||
- Additional View Settings.
|
||||
- Better print support
|
||||
- New Toolbox Page!
|
||||
- Bulk assign categories and tags by keyword search
|
||||
- Title case all Categories or Tags with 1 click
|
||||
|
@ -45,8 +61,8 @@
|
|||
- Recipe Cards now have a menu button for quick actions!
|
||||
- Edit
|
||||
- Delete
|
||||
- Download (As Json)
|
||||
- Copy Link
|
||||
- Integrated Share with supported OS/Browsers
|
||||
- Print
|
||||
- New Profile Dashboard!
|
||||
- Edit Your Profile
|
||||
- Create/Edit Themes
|
||||
|
@ -58,13 +74,17 @@
|
|||
- See uncategorized/untagged recipes and organize them!
|
||||
- Backup/Restore right from your dashboard
|
||||
- See server side events. Now you can know who deleted your favorite recipe!
|
||||
- New Event Notifications through the Apprise Library
|
||||
- Get notified when specific server side events occur
|
||||
|
||||
### Performance
|
||||
- Images are now served up by the Caddy increase performance and offloading some loads from the API server
|
||||
- Requesting all recipes from the server has been rewritten to refresh less often and manage client side data better.
|
||||
- All images are now converted to .webp for better compression
|
||||
### Meal Planner
|
||||
- Multiple Recipes per day
|
||||
- Supports meals without recipes (Enter title and description)
|
||||
- Generate share-link from created meal-planners
|
||||
- Shopping lists can be directly generated from the meal plan
|
||||
|
||||
### General
|
||||
- User can now favorite recipes
|
||||
- New 'Dark' Color Theme Packaged with Mealie
|
||||
- Updated Recipe Card Sections Toolbar
|
||||
- New Sort Options (They work this time!)
|
||||
|
@ -88,7 +108,12 @@
|
|||
- Improved styling for search bar in desktop
|
||||
- Improved search layout on mobile
|
||||
- Profile image now shown on all sidebars
|
||||
- Switched from Flash Messages to Snackbar (Removed dependency
|
||||
- Switched from Flash Messages to Snackbar (Removed dependency)
|
||||
-
|
||||
### Performance
|
||||
- Images are now served up by the Caddy increase performance and offloading some loads from the API server
|
||||
- Requesting all recipes from the server has been rewritten to refresh less often and manage client side data better.
|
||||
- All images are now converted to .webp for better compression
|
||||
|
||||
### Behind the Scenes
|
||||
- Black and Flake8 now run as CI/CD checks
|
||||
|
|
|
@ -3,7 +3,7 @@ Your sites settings panel can only be accessed by administrators. This where you
|
|||
|
||||
## Home Page Settings
|
||||
| Option | Description |
|
||||
| ------------------ | -------------------------------------------------------------- |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| Show Recent | To display the recent recipes section on the home page |
|
||||
| Card Per Section | The amount of cards displayed in each section on the home page |
|
||||
| Home Page Sections | Category sections to include on the home page |
|
||||
|
|
|
@ -2,29 +2,8 @@
|
|||
|
||||
## Getting a Token
|
||||
|
||||
Mealie supports long-live api tokens in the user frontend. In you profile section you can use the
|
||||
Mealie supports long-live api tokens in the user frontend. See [user settings page](../../users-groups/user-settings/)
|
||||
|
||||
### Curl
|
||||
```bash
|
||||
curl -X 'POST' \
|
||||
'https://mealie-demo.hay-kot.dev/api/auth/token' \
|
||||
-H 'accept: application/json' \
|
||||
-H 'Content-Type: application/x-www-form-urlencoded' \
|
||||
-d 'grant_type=&username=changeme%40email.com&password=demo&scope=&client_id=&client_secret='
|
||||
|
||||
```
|
||||
|
||||
#### Response
|
||||
```json
|
||||
{
|
||||
"snackbar": {
|
||||
"text": "User Successfully Logged In",
|
||||
"type": "success"
|
||||
},
|
||||
"access_token": "your-long-token-string",
|
||||
"token_type": "bearer"
|
||||
}
|
||||
```
|
||||
|
||||
## Key Components
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
# Recipes
|
||||
|
||||
## URL Import
|
||||
Adding a recipe can be as easy as clicking in the bottom-right corner, copying the recipe URL into Mealie and letting the web scrapper organize information. Currently this scraper is implemented with [scrape-schema-recipe package](https://pypi.org/project/scrape-schema-recipe/). You may have mixed results on some websites, especially with blogs or non-specific recipe websites. See the bulk import Option below for another a convenient way to add blog style recipes into Mealie.
|
||||
You can add different sections to make sure your recipe is divided correctly into separate 'chapters'
|
||||
Adding a recipe can be as easy as clicking in the bottom-right corner, copying the recipe URL into Mealie and letting the web scrapper organize information. Currently this scraper is implemented with [recipe-scrapers](https://github.com/hhursev/recipe-scrapers). You may have mixed results on some websites, especially with blogs or non-specific recipe websites. See the bulk import Option below for another a convenient way to add blog style recipes into Mealie.
|
||||
|
||||
!!! tip
|
||||
You can find a list of some of the supported sites in the recipe-scrapers repo. If you're site isn't supported, you can work with the recipe-scrapers team to implement it and we can down-stream those changes into Mealie.
|
||||
|
||||
![](../../assets/gifs/URL-import.gif)
|
||||
|
||||
## Using Bookmarklets
|
||||
|
@ -19,12 +22,33 @@ window.open(dest, '_blank')
|
|||
```
|
||||
|
||||
## Recipe Editor
|
||||
|
||||
![edit-recipe](../../assets/img/edit-recipe.webp){: align=right style="height:225px;width:275px"}
|
||||
Recipes can be edited and created via the UI. This is done with both a form based approach where you have a UI to work with as well as with a in browser JSON Editor. The JSON editor allows you to easily copy and paste data from other sources.
|
||||
![edit-recipe](../../assets/img/edit-recipe.webp)
|
||||
|
||||
You can also add a custom recipe with the UI editor built into the web view.
|
||||
You can also add a custom recipe with the UI editor built into the web view. Using the `+` button on the site.
|
||||
|
||||
### Recipe Settings
|
||||
|
||||
Settings for a specific recipe can be adjusted in the settings menu inside the editor. Currently the settings supports
|
||||
|
||||
- Settings a Recipe to Public/Private
|
||||
- Show Nutrition Values
|
||||
- Show Assets
|
||||
- Landscape Mode (Coming Soon)
|
||||
|
||||
!!! note
|
||||
Recipes set to private will only be displayed when a user is logged in. Currently there is no way to generate a share-link for a private recipe, but it is on the roadmap.
|
||||
|
||||
### Recipe Assets
|
||||
|
||||
While in the editor you also have an opportunity to upload any asset to your recipe. There are several icons that you can choose from or you can choose an arbitrary file icon. Once uploaded you can view or download the asset when viewing the page.
|
||||
|
||||
!!! tip
|
||||
You can get a link to an asset to embed in a recipe step by select the copy icon in editor mode.
|
||||
|
||||
### Bulk Import
|
||||
|
||||
## Bulk Import
|
||||
Mealie also supports bulk import of recipe instructions and ingredients. Select "Bulk Add" in the editor and paste in your plain text data to be parsed. Each line is treated as one entry and will be appended to the existing ingredients or instructions if they exist. Empty lines will be stripped from the text.
|
||||
|
||||
![](../../assets/gifs/bulk-add-demo.gif)
|
||||
|
|
|
@ -1,21 +1,6 @@
|
|||
#Toolbox
|
||||
The toolbox gives you multiple options to clean-up and organize your recipes. You can get notified through different channels.
|
||||
You can access it through the 'Settings' menu or through the [dashboard](../admin/dashboard.md).
|
||||
# External Notifications
|
||||
|
||||
|
||||
## Category and Tag Editor
|
||||
The 'Categories' and 'Tags' tab give you the option to bulk assign categories and tags to multiple recipes. You could also remove the unused ones or title case them all.
|
||||
|
||||
![Toolbox-Categories](../../assets/img/Toolbox-Categories.webp)
|
||||
|
||||
## Bulk Organize
|
||||
The 'Organize' tab can be used to show all of the items that do not have any category or tag assigned.
|
||||
|
||||
![Toolbox-Organize](../../assets/img/Toolbox-Organize.webp)
|
||||
|
||||
## External Notifications
|
||||
|
||||
### Apprise
|
||||
## Apprise
|
||||
|
||||
Using the [Apprise](https://github.com/caronc/apprise/) library Mealie is able to provided notification services for nearly every popular service. Some of our favorites are...
|
||||
|
||||
|
@ -28,7 +13,7 @@ Using the [Apprise](https://github.com/caronc/apprise/) library Mealie is able t
|
|||
But there are some many to choose from! Take a look at their wiki for information on how to create their URL formats and that you can use to create a notification integration in Mealie.
|
||||
|
||||
|
||||
### Subscribe Events
|
||||
## Subscribe Events
|
||||
There are several categories of events that mealie logs that can be broadcast with the notifications feature. You can also see a feed of your events in the Admin Dashboard
|
||||
|
||||
- General Events
|
||||
|
@ -55,7 +40,7 @@ In most cases the events will also provide details on which user performed the a
|
|||
This is a new feature and we are still working through all the possibilities of events. if you have an idea for an event let us know!
|
||||
|
||||
|
||||
### Creating a New Notification
|
||||
## Creating a New Notification
|
||||
|
||||
New events can be created and viewed in admin Toolbox `/admin/toolbox?tab=event-notifications`. Select the "+ Notification" button and you'll be provided with a dialog. Complete the form using the URL for the service you'd like to connect to. Before saving be sure to use the test feature.
|
||||
|
17
docs/docs/documentation/toolbox/organize-tools.md
Normal file
17
docs/docs/documentation/toolbox/organize-tools.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
#Toolbox
|
||||
The toolbox gives you multiple options to clean-up and organize your recipes. You can get notified through different channels.
|
||||
You can access it through the 'Settings' menu or through the [dashboard](../admin/dashboard.md).
|
||||
|
||||
|
||||
## Category and Tag Editor
|
||||
|
||||
The 'Categories' and 'Tags' tab give you the option to bulk assign categories and tags to multiple recipes. You could also remove the unused ones or title case them all.
|
||||
|
||||
![Toolbox-Categories](../../assets/img/Toolbox-Categories.webp)
|
||||
|
||||
## Bulk Organize
|
||||
|
||||
The 'Organize' tab can be used to show all of the items that do not have any category or tag assigned.
|
||||
|
||||
![Toolbox-Organize](../../assets/img/Toolbox-Organize.webp)
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
# Meal Planner
|
||||
|
||||
## Working with Planner
|
||||
In Mealie you can create a meal plan based off the calendar inputs on the meal planner page. There is no limit to how long or how short a meal plan is.
|
||||
You may also create duplicate meal plans for the same date range. After selecting your date range, click on the card for each day and search through recipes to find your choice. Add a side-dish if you prefer to. After selecting a recipe for all meals, save the plan.
|
||||
|
||||
In Mealie you can create a meal plan based off the calendar inputs on the meal planner page. There is no limit to how long or how short a meal plan is. You may also create duplicate meal plans for the same date range. After selecting your date range, click on the card for each day and search through recipes to find your choice. Add a side-dish if you prefer to. After selecting a recipe for all meals, save the plan. Selecting the 'No Recipe' button will allow you to add an entry without a recipe by providing a title and description
|
||||
|
||||
You can also randomly generate meal plans with the dice-button at the bottom.
|
||||
|
||||
To edit the meal in a meal plan simply select the edit button on the card in the timeline. Similarly, to delete a meal plan click the delete button on the card in the timeline. Currently, there is no support to change the date range in a meal plan.
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
# User Settings
|
||||
|
||||
A user will be able to access 3 sections in their admin panel. The user profile, themes, group/meal-plan settings section.
|
||||
|
||||
## Profile Settings
|
||||
In as users profile they are able to
|
||||
In the users profile they are able to:
|
||||
|
||||
- Change Display Name
|
||||
- Change Email
|
||||
- Update Password
|
||||
- View Their Group
|
||||
- Upgrade Profile Picture (Experimental)
|
||||
- Update Profile Picture (Experimental)
|
||||
- Create API Keys
|
||||
|
||||
## Themes
|
||||
Color themes can be created and set from the UI in the Settings-Profile page. You can select an existing color theme or create a new one. On creation of a new color theme, the default colors will be used, then you can select and save as you'd like. By default, the "default" theme will be loaded for all new users visiting the site. All created color themes are available to all users of the site. Theme Colors will be set for both light and dark modes.
|
||||
|
@ -23,3 +22,12 @@ Color themes can be created and set from the UI in the Settings-Profile page. Yo
|
|||
In the meal planner section a user can select categories to be used as a part of the random recipe selector in the meal plan creator. If no categories are selected, all recipes will be used
|
||||
|
||||
Meal planner webhooks are post requests sent from Mealie to an external endpoint. The body of the message is the Recipe JSON of the scheduled meal. If no meal is schedule, no request is sent. The webhook functionality can be enabled or disabled as well as scheduled. Note that you must "Save" prior to any changes taking affect server side.
|
||||
|
||||
## API Key Generation
|
||||
Users can quickly and easily generate API keys with the user interface. Provide a name for your token and then you are shown 1 time the generated API key. If you ever loose the API key you are not able to identify or retrieve it from the UI.
|
||||
|
||||
![API Key Image](../../assets/img/api-key-image-v1.webp)
|
||||
|
||||
|
||||
!!! warning
|
||||
API keys are stored in plain text in the database.
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,7 @@
|
|||
site_name: Mealie
|
||||
demo_url: https://mealie-demo.hay-kot.dev/
|
||||
site_url: https://hay-kot.github.io/mealie/
|
||||
use_directory_urls: true
|
||||
theme:
|
||||
palette:
|
||||
# Light mode
|
||||
|
@ -61,6 +63,7 @@ nav:
|
|||
- Users & Groups:
|
||||
- User Settings: "documentation/users-groups/user-settings.md"
|
||||
- Planning Meals: "documentation/users-groups/meal-planner.md"
|
||||
|
||||
- Admin:
|
||||
- Dashboard: "documentation/admin/dashboard.md"
|
||||
- Site Settings: "documentation/admin/site-settings.md"
|
||||
|
@ -68,15 +71,16 @@ nav:
|
|||
- User Management: "documentation/admin/user-management.md"
|
||||
- Backups and Restore: "documentation/admin/backups-and-exports.md"
|
||||
- Recipe Migration: "documentation/admin/migration-imports.md"
|
||||
|
||||
- Toolbox:
|
||||
- Toolbox: "documentation/toolbox/toolbox-intro.md"
|
||||
- External Notifications: "documentation/toolbox/notifications.md"
|
||||
- Organization Tools: "documentation/toolbox/organize-tools.md"
|
||||
|
||||
- Community Guides:
|
||||
- iOS Shortcuts: "documentation/community-guide/ios.md"
|
||||
- Reverse Proxy (SWAG): "documentation/community-guide/swag.md"
|
||||
- Home Assistant: "documentation/community-guide/home-assistant.md"
|
||||
- Bulk Url Import: "documentation/community-guide/bulk-url-import.md"
|
||||
|
||||
- API Reference: "api/redoc.md"
|
||||
- Contributors Guide:
|
||||
- Non-Code: "contributors/non-coders.md"
|
||||
|
|
154
frontend/package-lock.json
generated
154
frontend/package-lock.json
generated
|
@ -1947,16 +1947,15 @@
|
|||
}
|
||||
},
|
||||
"@vue/component-compiler-utils": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz",
|
||||
"integrity": "sha512-lejBLa7xAMsfiZfNp7Kv51zOzifnb29FwdnMLa96z26kXErPFioSf9BMcePVIQ6/Gc6/mC0UrPpxAWIHyae0vw==",
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.1.tgz",
|
||||
"integrity": "sha512-Mci9WJYLRjyJEBkGHMPxZ1ihJ9l6gOy2Gr6hpYZUNpQoe5+nbpeb3w00aP+PSHJygCF+fxJsqp7Af1zGDITzuw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"consolidate": "^0.15.1",
|
||||
"hash-sum": "^1.0.2",
|
||||
"lru-cache": "^4.1.2",
|
||||
"merge-source-map": "^1.1.0",
|
||||
"postcss": "^7.0.14",
|
||||
"postcss-selector-parser": "^6.0.2",
|
||||
"prettier": "^1.18.2",
|
||||
"source-map": "~0.6.1",
|
||||
|
@ -4641,12 +4640,20 @@
|
|||
"dev": true
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
|
||||
"integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
|
||||
"integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "1"
|
||||
"domelementtype": "^2.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"domelementtype": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
|
||||
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
|
@ -6163,34 +6170,43 @@
|
|||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
|
||||
"integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
|
||||
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "^1.3.1",
|
||||
"domhandler": "^2.3.0",
|
||||
"domutils": "^1.5.1",
|
||||
"entities": "^1.1.1",
|
||||
"inherits": "^2.0.1",
|
||||
"readable-stream": "^3.1.1"
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.0.0",
|
||||
"domutils": "^2.5.2",
|
||||
"entities": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"entities": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
|
||||
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
|
||||
"dev": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"dom-serializer": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
|
||||
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
|
||||
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
|
||||
"dev": true
|
||||
},
|
||||
"domutils": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
|
||||
"integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9680,16 +9696,16 @@
|
|||
"dev": true
|
||||
},
|
||||
"renderkid": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz",
|
||||
"integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==",
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz",
|
||||
"integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"css-select": "^2.0.2",
|
||||
"dom-converter": "^0.2",
|
||||
"htmlparser2": "^3.10.1",
|
||||
"lodash": "^4.17.20",
|
||||
"strip-ansi": "^3.0.0"
|
||||
"css-select": "^4.1.3",
|
||||
"dom-converter": "^0.2.0",
|
||||
"htmlparser2": "^6.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"strip-ansi": "^3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
|
@ -9698,6 +9714,62 @@
|
|||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true
|
||||
},
|
||||
"css-select": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
|
||||
"integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-what": "^5.0.0",
|
||||
"domhandler": "^4.2.0",
|
||||
"domutils": "^2.6.0",
|
||||
"nth-check": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"css-what": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
|
||||
"integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
|
||||
"dev": true
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
|
||||
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
|
||||
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
|
||||
"dev": true
|
||||
},
|
||||
"domutils": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
|
||||
"integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"nth-check": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz",
|
||||
"integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolbase": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
|
@ -11907,9 +11979,9 @@
|
|||
}
|
||||
},
|
||||
"vue-loader": {
|
||||
"version": "15.9.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.6.tgz",
|
||||
"integrity": "sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg==",
|
||||
"version": "15.9.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.7.tgz",
|
||||
"integrity": "sha512-qzlsbLV1HKEMf19IqCJqdNvFJRCI58WNbS6XbPqK13MrLz65es75w392MSQ5TsARAfIjUw+ATm3vlCXUJSOH9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@vue/component-compiler-utils": "^3.1.0",
|
||||
|
|
|
@ -1,55 +1,38 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import i18n from "@/i18n.js";
|
||||
|
||||
const prefix = baseURL + "about";
|
||||
|
||||
const aboutURLs = {
|
||||
version: `${prefix}/version`,
|
||||
debug: `${prefix}`,
|
||||
lastRecipe: `${prefix}/last-recipe-json`,
|
||||
demo: `${prefix}/is-demo`,
|
||||
log: num => `${prefix}/log/${num}`,
|
||||
statistics: `${prefix}/statistics`,
|
||||
events: `${prefix}/events`,
|
||||
event: id => `${prefix}/events/${id}`,
|
||||
|
||||
allNotifications: `${prefix}/events/notifications`,
|
||||
testNotifications: `${prefix}/events/notifications/test`,
|
||||
notification: id => `${prefix}/events/notifications/${id}`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
export const aboutAPI = {
|
||||
async getEvents() {
|
||||
const resposne = await apiReq.get(aboutURLs.events);
|
||||
const resposne = await apiReq.get(API_ROUTES.aboutEvents);
|
||||
return resposne.data;
|
||||
},
|
||||
async deleteEvent(id) {
|
||||
const resposne = await apiReq.delete(aboutURLs.event(id));
|
||||
const resposne = await apiReq.delete(API_ROUTES.aboutEventsId(id));
|
||||
return resposne.data;
|
||||
},
|
||||
async deleteAllEvents() {
|
||||
const resposne = await apiReq.delete(aboutURLs.events);
|
||||
const resposne = await apiReq.delete(API_ROUTES.aboutEvents);
|
||||
return resposne.data;
|
||||
},
|
||||
|
||||
async allEventNotifications() {
|
||||
const response = await apiReq.get(aboutURLs.allNotifications);
|
||||
const response = await apiReq.get(API_ROUTES.aboutEventsNotifications);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async createNotification(data) {
|
||||
const response = await apiReq.post(aboutURLs.allNotifications, data);
|
||||
const response = await apiReq.post(API_ROUTES.aboutEventsNotifications, data);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async deleteNotification(id) {
|
||||
const response = await apiReq.delete(aboutURLs.notification(id));
|
||||
const response = await apiReq.delete(API_ROUTES.aboutEventsNotificationsId(id));
|
||||
return response.data;
|
||||
},
|
||||
async testNotificationByID(id) {
|
||||
const response = await apiReq.post(
|
||||
aboutURLs.testNotifications,
|
||||
API_ROUTES.aboutEventsNotificationsTest,
|
||||
{ id: id },
|
||||
() => i18n.t("events.something-went-wrong"),
|
||||
() => i18n.t("events.test-message-sent")
|
||||
|
@ -58,7 +41,7 @@ export const aboutAPI = {
|
|||
},
|
||||
async testNotificationByURL(url) {
|
||||
const response = await apiReq.post(
|
||||
aboutURLs.testNotifications,
|
||||
API_ROUTES.aboutEventsNotificationsTest,
|
||||
{ test_url: url },
|
||||
() => i18n.t("events.something-went-wrong"),
|
||||
() => i18n.t("events.test-message-sent")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const baseURL = "/api/";
|
||||
import { prefix } from "./apiRoutes";
|
||||
import axios from "axios";
|
||||
import { store } from "../store";
|
||||
import { utils } from "@/utils";
|
||||
|
@ -66,11 +66,10 @@ const apiReq = {
|
|||
const response = await this.get(url);
|
||||
const token = response.data.fileToken;
|
||||
|
||||
const tokenURL = baseURL + "utils/download?token=" + token;
|
||||
const tokenURL = prefix + "utils/download?token=" + token;
|
||||
window.open(tokenURL, "_blank");
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
||||
export { apiReq };
|
||||
export { baseURL };
|
||||
|
|
|
@ -1,82 +1,87 @@
|
|||
// This Content is Auto Generated
|
||||
const prefix = '/api'
|
||||
export const prefix = "/api";
|
||||
export const API_ROUTES = {
|
||||
aboutEvents: "/api/about/events",
|
||||
aboutEventsNotifications: "/api/about/events/notifications",
|
||||
aboutEventsNotificationsTest: "/api/about/events/notifications/test",
|
||||
authRefresh: "/api/auth/refresh",
|
||||
authToken: "/api/auth/token",
|
||||
authTokenLong: "/api/auth/token/long",
|
||||
backupsAvailable: "/api/backups/available",
|
||||
backupsExportDatabase: "/api/backups/export/database",
|
||||
backupsUpload: "/api/backups/upload",
|
||||
categories: "/api/categories",
|
||||
categoriesEmpty: "/api/categories/empty",
|
||||
debug: "/api/debug",
|
||||
debugLastRecipeJson: "/api/debug/last-recipe-json",
|
||||
debugLog: "/api/debug/log",
|
||||
debugStatistics: "/api/debug/statistics",
|
||||
debugVersion: "/api/debug/version",
|
||||
groups: "/api/groups",
|
||||
groupsSelf: "/api/groups/self",
|
||||
mealPlansAll: "/api/meal-plans/all",
|
||||
mealPlansCreate: "/api/meal-plans/create",
|
||||
mealPlansThisWeek: "/api/meal-plans/this-week",
|
||||
mealPlansToday: "/api/meal-plans/today",
|
||||
mealPlansTodayImage: "/api/meal-plans/today/image",
|
||||
migrations: "/api/migrations",
|
||||
recipesCategory: "/api/recipes/category",
|
||||
recipesCreate: "/api/recipes/create",
|
||||
recipesCreateUrl: "/api/recipes/create-url",
|
||||
recipesSummary: "/api/recipes/summary",
|
||||
recipesSummaryUncategorized: "/api/recipes/summary/uncategorized",
|
||||
recipesSummaryUntagged: "/api/recipes/summary/untagged",
|
||||
recipesTag: "/api/recipes/tag",
|
||||
shoppingLists: "/api/shopping-lists",
|
||||
siteSettings: "/api/site-settings",
|
||||
siteSettingsCustomPages: "/api/site-settings/custom-pages",
|
||||
siteSettingsWebhooksTest: "/api/site-settings/webhooks/test",
|
||||
tags: "/api/tags",
|
||||
tagsEmpty: "/api/tags/empty",
|
||||
themes: "/api/themes",
|
||||
themesCreate: "/api/themes/create",
|
||||
users: "/api/users",
|
||||
usersApiTokens: "/api/users-tokens",
|
||||
usersSelf: "/api/users/self",
|
||||
usersSignUps: "/api/users/sign-ups",
|
||||
utilsDownload: "/api/utils/download",
|
||||
aboutEvents: `${prefix}/about/events`,
|
||||
aboutEventsNotifications: `${prefix}/about/events/notifications`,
|
||||
aboutEventsNotificationsTest: `${prefix}/about/events/notifications/test`,
|
||||
authRefresh: `${prefix}/auth/refresh`,
|
||||
authToken: `${prefix}/auth/token`,
|
||||
authTokenLong: `${prefix}/auth/token/long`,
|
||||
backupsAvailable: `${prefix}/backups/available`,
|
||||
backupsExportDatabase: `${prefix}/backups/export/database`,
|
||||
backupsUpload: `${prefix}/backups/upload`,
|
||||
categories: `${prefix}/categories`,
|
||||
categoriesEmpty: `${prefix}/categories/empty`,
|
||||
debug: `${prefix}/debug`,
|
||||
debugLastRecipeJson: `${prefix}/debug/last-recipe-json`,
|
||||
debugLog: `${prefix}/debug/log`,
|
||||
debugStatistics: `${prefix}/debug/statistics`,
|
||||
debugVersion: `${prefix}/debug/version`,
|
||||
groups: `${prefix}/groups`,
|
||||
groupsSelf: `${prefix}/groups/self`,
|
||||
mealPlansAll: `${prefix}/meal-plans/all`,
|
||||
mealPlansCreate: `${prefix}/meal-plans/create`,
|
||||
mealPlansThisWeek: `${prefix}/meal-plans/this-week`,
|
||||
mealPlansToday: `${prefix}/meal-plans/today`,
|
||||
mealPlansTodayImage: `${prefix}/meal-plans/today/image`,
|
||||
migrations: `${prefix}/migrations`,
|
||||
recipesCategory: `${prefix}/recipes/category`,
|
||||
recipesCreate: `${prefix}/recipes/create`,
|
||||
recipesCreateUrl: `${prefix}/recipes/create-url`,
|
||||
recipesSummary: `${prefix}/recipes/summary`,
|
||||
recipesSummaryUncategorized: `${prefix}/recipes/summary/uncategorized`,
|
||||
recipesSummaryUntagged: `${prefix}/recipes/summary/untagged`,
|
||||
recipesTag: `${prefix}/recipes/tag`,
|
||||
recipesTestScrapeUrl: `${prefix}/recipes/test-scrape-url`,
|
||||
shoppingLists: `${prefix}/shopping-lists`,
|
||||
siteSettings: `${prefix}/site-settings`,
|
||||
siteSettingsCustomPages: `${prefix}/site-settings/custom-pages`,
|
||||
siteSettingsWebhooksTest: `${prefix}/site-settings/webhooks/test`,
|
||||
tags: `${prefix}/tags`,
|
||||
tagsEmpty: `${prefix}/tags/empty`,
|
||||
themes: `${prefix}/themes`,
|
||||
themesCreate: `${prefix}/themes/create`,
|
||||
users: `${prefix}/users`,
|
||||
usersApiTokens: `${prefix}/users-tokens`,
|
||||
usersSelf: `${prefix}/users/self`,
|
||||
usersSignUps: `${prefix}/users/sign-ups`,
|
||||
utilsDownload: `${prefix}/utils/download`,
|
||||
|
||||
aboutEventsId: (id) => `${prefix}/about/events/${id}`,
|
||||
aboutEventsNotificationsId: (id) => `${prefix}/about/events/notifications/${id}`,
|
||||
backupsFileNameDelete: (file_name) => `${prefix}/backups/${file_name}/delete`,
|
||||
backupsFileNameDownload: (file_name) => `${prefix}/backups/${file_name}/download`,
|
||||
backupsFileNameImport: (file_name) => `${prefix}/backups/${file_name}/import`,
|
||||
categoriesCategory: (category) => `${prefix}/categories/${category}`,
|
||||
debugLogNum: (num) => `${prefix}/debug/log/${num}`,
|
||||
groupsId: (id) => `${prefix}/groups/${id}`,
|
||||
mealPlansId: (id) => `${prefix}/meal-plans/${id}`,
|
||||
mealPlansIdShoppingList: (id) => `${prefix}/meal-plans/${id}/shopping-list`,
|
||||
mealPlansPlanId: (plan_id) => `${prefix}/meal-plans/${plan_id}`,
|
||||
mediaRecipesRecipeSlugAssetsFileName: (recipe_slug, file_name) => `${prefix}/media/recipes/${recipe_slug}/assets/${file_name}`,
|
||||
mediaRecipesRecipeSlugImagesFileName: (recipe_slug, file_name) => `${prefix}/media/recipes/${recipe_slug}/images/${file_name}`,
|
||||
migrationsImportTypeFileNameDelete: (import_type, file_name) => `${prefix}/migrations/${import_type}/${file_name}/delete`,
|
||||
migrationsImportTypeFileNameImport: (import_type, file_name) => `${prefix}/migrations/${import_type}/${file_name}/import`,
|
||||
migrationsImportTypeUpload: (import_type) => `${prefix}/migrations/${import_type}/upload`,
|
||||
recipesRecipeSlug: (recipe_slug) => `${prefix}/recipes/${recipe_slug}`,
|
||||
recipesRecipeSlugAssets: (recipe_slug) => `${prefix}/recipes/${recipe_slug}/assets`,
|
||||
recipesRecipeSlugImage: (recipe_slug) => `${prefix}/recipes/${recipe_slug}/image`,
|
||||
recipesSlugComments: (slug) => `${prefix}/recipes/${slug}/comments`,
|
||||
aboutEventsId: id => `${prefix}/about/events/${id}`,
|
||||
aboutEventsNotificationsId: id => `${prefix}/about/events/notifications/${id}`,
|
||||
backupsFileNameDelete: file_name => `${prefix}/backups/${file_name}/delete`,
|
||||
backupsFileNameDownload: file_name => `${prefix}/backups/${file_name}/download`,
|
||||
backupsFileNameImport: file_name => `${prefix}/backups/${file_name}/import`,
|
||||
categoriesCategory: category => `${prefix}/categories/${category}`,
|
||||
debugLogNum: num => `${prefix}/debug/log/${num}`,
|
||||
groupsId: id => `${prefix}/groups/${id}`,
|
||||
mealPlansId: id => `${prefix}/meal-plans/${id}`,
|
||||
mealPlansIdShoppingList: id => `${prefix}/meal-plans/${id}/shopping-list`,
|
||||
mealPlansPlanId: plan_id => `${prefix}/meal-plans/${plan_id}`,
|
||||
mediaRecipesRecipeSlugAssetsFileName: (recipe_slug, file_name) =>
|
||||
`${prefix}/media/recipes/${recipe_slug}/assets/${file_name}`,
|
||||
mediaRecipesRecipeSlugImagesFileName: (recipe_slug, file_name) =>
|
||||
`${prefix}/media/recipes/${recipe_slug}/images/${file_name}`,
|
||||
migrationsImportTypeFileNameDelete: (import_type, file_name) =>
|
||||
`${prefix}/migrations/${import_type}/${file_name}/delete`,
|
||||
migrationsImportTypeFileNameImport: (import_type, file_name) =>
|
||||
`${prefix}/migrations/${import_type}/${file_name}/import`,
|
||||
migrationsImportTypeUpload: import_type => `${prefix}/migrations/${import_type}/upload`,
|
||||
recipesRecipeSlug: recipe_slug => `${prefix}/recipes/${recipe_slug}`,
|
||||
recipesRecipeSlugAssets: recipe_slug => `${prefix}/recipes/${recipe_slug}/assets`,
|
||||
recipesRecipeSlugImage: recipe_slug => `${prefix}/recipes/${recipe_slug}/image`,
|
||||
recipesSlugComments: slug => `${prefix}/recipes/${slug}/comments`,
|
||||
recipesSlugCommentsId: (slug, id) => `${prefix}/recipes/${slug}/comments/${id}`,
|
||||
shoppingListsId: (id) => `${prefix}/shopping-lists/${id}`,
|
||||
siteSettingsCustomPagesId: (id) => `${prefix}/site-settings/custom-pages/${id}`,
|
||||
tagsTag: (tag) => `${prefix}/tags/${tag}`,
|
||||
themesId: (id) => `${prefix}/themes/${id}`,
|
||||
usersApiTokensTokenId: (token_id) => `${prefix}/users-tokens/${token_id}`,
|
||||
usersId: (id) => `${prefix}/users/${id}`,
|
||||
usersIdFavorites: (id) => `${prefix}/users/${id}/favorites`,
|
||||
shoppingListsId: id => `${prefix}/shopping-lists/${id}`,
|
||||
siteSettingsCustomPagesId: id => `${prefix}/site-settings/custom-pages/${id}`,
|
||||
tagsTag: tag => `${prefix}/tags/${tag}`,
|
||||
themesId: id => `${prefix}/themes/${id}`,
|
||||
usersApiTokensTokenId: token_id => `${prefix}/users-tokens/${token_id}`,
|
||||
usersId: id => `${prefix}/users/${id}`,
|
||||
usersIdFavorites: id => `${prefix}/users/${id}/favorites`,
|
||||
usersIdFavoritesSlug: (id, slug) => `${prefix}/users/${id}/favorites/${slug}`,
|
||||
usersIdImage: (id) => `${prefix}/users/${id}/image`,
|
||||
usersIdPassword: (id) => `${prefix}/users/${id}/password`,
|
||||
usersIdResetPassword: (id) => `${prefix}/users/${id}/reset-password`,
|
||||
usersSignUpsToken: (token) => `${prefix}/users/sign-ups/${token}`,
|
||||
}
|
||||
usersIdImage: id => `${prefix}/users/${id}/image`,
|
||||
usersIdPassword: id => `${prefix}/users/${id}/password`,
|
||||
usersIdResetPassword: id => `${prefix}/users/${id}/reset-password`,
|
||||
usersSignUpsToken: token => `${prefix}/users/sign-ups/${token}`,
|
||||
};
|
||||
|
|
|
@ -1,18 +1,7 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import { store } from "@/store";
|
||||
import i18n from "@/i18n.js";
|
||||
|
||||
const backupBase = baseURL + "backups/";
|
||||
|
||||
export const backupURLs = {
|
||||
// Backup
|
||||
available: `${backupBase}available`,
|
||||
createBackup: `${backupBase}export/database`,
|
||||
importBackup: fileName => `${backupBase}${fileName}/import`,
|
||||
deleteBackup: fileName => `${backupBase}${fileName}/delete`,
|
||||
downloadBackup: fileName => `${backupBase}${fileName}/download`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
export const backupAPI = {
|
||||
/**
|
||||
|
@ -20,7 +9,7 @@ export const backupAPI = {
|
|||
* @returns {Array} List of Available Backups
|
||||
*/
|
||||
async requestAvailable() {
|
||||
let response = await apiReq.get(backupURLs.available);
|
||||
let response = await apiReq.get(API_ROUTES.backupsAvailable);
|
||||
return response.data;
|
||||
},
|
||||
/**
|
||||
|
@ -30,7 +19,7 @@ export const backupAPI = {
|
|||
* @returns A report containing status of imported items
|
||||
*/
|
||||
async import(fileName, data) {
|
||||
let response = await apiReq.post(backupURLs.importBackup(fileName), data);
|
||||
let response = await apiReq.post(API_ROUTES.backupsFileNameImport(fileName), data);
|
||||
store.dispatch("requestRecentRecipes");
|
||||
return response;
|
||||
},
|
||||
|
@ -40,7 +29,7 @@ export const backupAPI = {
|
|||
*/
|
||||
async delete(fileName) {
|
||||
return apiReq.delete(
|
||||
backupURLs.deleteBackup(fileName),
|
||||
API_ROUTES.backupsFileNameDelete(fileName),
|
||||
null,
|
||||
() => i18n.t("settings.backup.unable-to-delete-backup"),
|
||||
() => i18n.t("settings.backup.backup-deleted")
|
||||
|
@ -53,7 +42,7 @@ export const backupAPI = {
|
|||
*/
|
||||
async create(options) {
|
||||
return apiReq.post(
|
||||
backupURLs.createBackup,
|
||||
API_ROUTES.backupsExportDatabase,
|
||||
options,
|
||||
() => i18n.t("settings.backup.error-creating-backup-see-log-file"),
|
||||
response => {
|
||||
|
@ -67,7 +56,7 @@ export const backupAPI = {
|
|||
* @returns Download URL
|
||||
*/
|
||||
async download(fileName) {
|
||||
const url = backupURLs.downloadBackup(fileName);
|
||||
const url = API_ROUTES.backupsFileNameDownload(fileName);
|
||||
apiReq.download(url);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,30 +1,20 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import { store } from "@/store";
|
||||
import i18n from "@/i18n.js";
|
||||
|
||||
const prefix = baseURL + "categories";
|
||||
|
||||
const categoryURLs = {
|
||||
getAll: `${prefix}`,
|
||||
getEmpty: `${prefix}/empty`,
|
||||
getCategory: category => `${prefix}/${category}`,
|
||||
deleteCategory: category => `${prefix}/${category}`,
|
||||
updateCategory: category => `${prefix}/${category}`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
export const categoryAPI = {
|
||||
async getAll() {
|
||||
let response = await apiReq.get(categoryURLs.getAll);
|
||||
let response = await apiReq.get(API_ROUTES.categories);
|
||||
return response.data;
|
||||
},
|
||||
async getEmpty() {
|
||||
let response = await apiReq.get(categoryURLs.getEmpty);
|
||||
let response = await apiReq.get(API_ROUTES.categoriesEmpty);
|
||||
return response.data;
|
||||
},
|
||||
async create(name) {
|
||||
const response = await apiReq.post(
|
||||
categoryURLs.getAll,
|
||||
API_ROUTES.categories,
|
||||
{ name: name },
|
||||
() => i18n.t("category.category-creation-failed"),
|
||||
() => i18n.t("category.category-created")
|
||||
|
@ -35,12 +25,12 @@ export const categoryAPI = {
|
|||
}
|
||||
},
|
||||
async getRecipesInCategory(category) {
|
||||
let response = await apiReq.get(categoryURLs.getCategory(category));
|
||||
let response = await apiReq.get(API_ROUTES.categoriesCategory(category));
|
||||
return response.data;
|
||||
},
|
||||
async update(name, newName, overrideRequest = false) {
|
||||
const response = await apiReq.put(
|
||||
categoryURLs.updateCategory(name),
|
||||
API_ROUTES.categoriesCategory(name),
|
||||
{ name: newName },
|
||||
() => i18n.t("category.category-update-failed"),
|
||||
() => i18n.t("category.category-updated")
|
||||
|
@ -52,7 +42,7 @@ export const categoryAPI = {
|
|||
},
|
||||
async delete(category, overrideRequest = false) {
|
||||
const response = await apiReq.delete(
|
||||
categoryURLs.deleteCategory(category),
|
||||
API_ROUTES.categoriesCategory(category),
|
||||
null,
|
||||
() => i18n.t("category.category-deletion-failed"),
|
||||
() => i18n.t("category.category-deleted")
|
||||
|
@ -64,28 +54,18 @@ export const categoryAPI = {
|
|||
},
|
||||
};
|
||||
|
||||
const tagPrefix = baseURL + "tags";
|
||||
|
||||
const tagURLs = {
|
||||
getAll: `${tagPrefix}`,
|
||||
getEmpty: `${tagPrefix}/empty`,
|
||||
getTag: tag => `${tagPrefix}/${tag}`,
|
||||
deleteTag: tag => `${tagPrefix}/${tag}`,
|
||||
updateTag: tag => `${tagPrefix}/${tag}`,
|
||||
};
|
||||
|
||||
export const tagAPI = {
|
||||
async getAll() {
|
||||
let response = await apiReq.get(tagURLs.getAll);
|
||||
let response = await apiReq.get(API_ROUTES.tags);
|
||||
return response.data;
|
||||
},
|
||||
async getEmpty() {
|
||||
let response = await apiReq.get(tagURLs.getEmpty);
|
||||
let response = await apiReq.get(API_ROUTES.tagsEmpty);
|
||||
return response.data;
|
||||
},
|
||||
async create(name) {
|
||||
const response = await apiReq.post(
|
||||
tagURLs.getAll,
|
||||
API_ROUTES.tags,
|
||||
{ name: name },
|
||||
() => i18n.t("tag.tag-creation-failed"),
|
||||
() => i18n.t("tag.tag-created")
|
||||
|
@ -96,12 +76,12 @@ export const tagAPI = {
|
|||
}
|
||||
},
|
||||
async getRecipesInTag(tag) {
|
||||
let response = await apiReq.get(tagURLs.getTag(tag));
|
||||
let response = await apiReq.get(API_ROUTES.tagsTag(tag));
|
||||
return response.data;
|
||||
},
|
||||
async update(name, newName, overrideRequest = false) {
|
||||
const response = await apiReq.put(
|
||||
tagURLs.updateTag(name),
|
||||
API_ROUTES.tagsTag(name),
|
||||
{ name: newName },
|
||||
() => i18n.t("tag.tag-update-failed"),
|
||||
() => i18n.t("tag.tag-updated")
|
||||
|
@ -116,7 +96,7 @@ export const tagAPI = {
|
|||
},
|
||||
async delete(tag, overrideRequest = false) {
|
||||
const response = await apiReq.delete(
|
||||
tagURLs.deleteTag(tag),
|
||||
API_ROUTES.tagsTag(tag),
|
||||
null,
|
||||
() => i18n.t("tag.tag-deletion-failed"),
|
||||
() => i18n.t("tag.tag-deleted")
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import i18n from "@/i18n.js";
|
||||
const groupPrefix = baseURL + "groups";
|
||||
|
||||
const groupsURLs = {
|
||||
groups: `${groupPrefix}`,
|
||||
create: `${groupPrefix}`,
|
||||
delete: id => `${groupPrefix}/${id}`,
|
||||
current: `${groupPrefix}/self`,
|
||||
update: id => `${groupPrefix}/${id}`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
function deleteErrorText(response) {
|
||||
switch (response.data.detail) {
|
||||
|
@ -29,31 +20,31 @@ function deleteErrorText(response) {
|
|||
|
||||
export const groupAPI = {
|
||||
async allGroups() {
|
||||
let response = await apiReq.get(groupsURLs.groups);
|
||||
let response = await apiReq.get(API_ROUTES.groups);
|
||||
return response.data;
|
||||
},
|
||||
create(name) {
|
||||
return apiReq.post(
|
||||
groupsURLs.create,
|
||||
API_ROUTES.groups,
|
||||
{ name: name },
|
||||
() => i18n.t("group.user-group-creation-failed"),
|
||||
() => i18n.t("group.user-group-created")
|
||||
);
|
||||
},
|
||||
delete(id) {
|
||||
return apiReq.delete(groupsURLs.delete(id), null, deleteErrorText, function() {
|
||||
return apiReq.delete(API_ROUTES.groupsId(id), null, deleteErrorText, function() {
|
||||
return i18n.t("group.group-deleted");
|
||||
});
|
||||
},
|
||||
async current() {
|
||||
const response = await apiReq.get(groupsURLs.current, null, null);
|
||||
const response = await apiReq.get(API_ROUTES.groupsSelf, null, null);
|
||||
if (response) {
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
update(data) {
|
||||
return apiReq.put(
|
||||
groupsURLs.update(data.id),
|
||||
API_ROUTES.groupsId(data.id),
|
||||
data,
|
||||
() => i18n.t("group.error-updating-group"),
|
||||
() => i18n.t("settings.group-settings-updated")
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import i18n from "@/i18n.js";
|
||||
|
||||
const prefix = baseURL + "meal-plans/";
|
||||
|
||||
const mealPlanURLs = {
|
||||
// Meals
|
||||
all: `${prefix}all`,
|
||||
create: `${prefix}create`,
|
||||
thisWeek: `${prefix}this-week`,
|
||||
byId: planID => `${prefix}${planID}`,
|
||||
update: planID => `${prefix}${planID}`,
|
||||
delete: planID => `${prefix}${planID}`,
|
||||
today: `${prefix}today`,
|
||||
shopping: planID => `${prefix}${planID}/shopping-list`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
export const mealplanAPI = {
|
||||
create(postBody) {
|
||||
return apiReq.post(
|
||||
mealPlanURLs.create,
|
||||
API_ROUTES.mealPlansCreate,
|
||||
postBody,
|
||||
() => i18n.t("meal-plan.mealplan-creation-failed"),
|
||||
() => i18n.t("meal-plan.mealplan-created")
|
||||
|
@ -27,28 +13,28 @@ export const mealplanAPI = {
|
|||
},
|
||||
|
||||
async all() {
|
||||
let response = await apiReq.get(mealPlanURLs.all);
|
||||
let response = await apiReq.get(API_ROUTES.mealPlansAll);
|
||||
return response;
|
||||
},
|
||||
|
||||
async thisWeek() {
|
||||
let response = await apiReq.get(mealPlanURLs.thisWeek);
|
||||
let response = await apiReq.get(API_ROUTES.mealPlansThisWeek);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async today() {
|
||||
let response = await apiReq.get(mealPlanURLs.today);
|
||||
let response = await apiReq.get(API_ROUTES.mealPlansToday);
|
||||
return response;
|
||||
},
|
||||
|
||||
async getById(id) {
|
||||
let response = await apiReq.get(mealPlanURLs.byId(id));
|
||||
let response = await apiReq.get(API_ROUTES.mealPlansId(id));
|
||||
return response.data;
|
||||
},
|
||||
|
||||
delete(id) {
|
||||
return apiReq.delete(
|
||||
mealPlanURLs.delete(id),
|
||||
API_ROUTES.mealPlansId(id),
|
||||
null,
|
||||
() => i18n.t("meal-plan.mealplan-deletion-failed"),
|
||||
() => i18n.t("meal-plan.mealplan-deleted")
|
||||
|
@ -57,7 +43,7 @@ export const mealplanAPI = {
|
|||
|
||||
update(id, body) {
|
||||
return apiReq.put(
|
||||
mealPlanURLs.update(id),
|
||||
API_ROUTES.mealPlansId(id),
|
||||
body,
|
||||
() => i18n.t("meal-plan.mealplan-update-failed"),
|
||||
() => i18n.t("meal-plan.mealplan-updated")
|
||||
|
@ -65,7 +51,7 @@ export const mealplanAPI = {
|
|||
},
|
||||
|
||||
async shoppingList(id) {
|
||||
let response = await apiReq.get(mealPlanURLs.shopping(id));
|
||||
let response = await apiReq.get(API_ROUTES.mealPlansIdShoppingList(id));
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,45 +1,29 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
|
||||
const prefix = baseURL + "debug";
|
||||
|
||||
const debugURLs = {
|
||||
version: `${prefix}/version`,
|
||||
debug: `${prefix}`,
|
||||
lastRecipe: `${prefix}/last-recipe-json`,
|
||||
demo: `${prefix}/is-demo`,
|
||||
log: num => `${prefix}/log/${num}`,
|
||||
statistics: `${prefix}/statistics`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
export const metaAPI = {
|
||||
async getAppInfo() {
|
||||
const response = await apiReq.get(debugURLs.version);
|
||||
const response = await apiReq.get(API_ROUTES.debugVersion);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getDebugInfo() {
|
||||
const response = await apiReq.get(debugURLs.debug);
|
||||
const response = await apiReq.get(API_ROUTES.debug);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getLogText(num) {
|
||||
const response = await apiReq.get(debugURLs.log(num));
|
||||
const response = await apiReq.get(API_ROUTES.debugLog(num));
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getLastJson() {
|
||||
const response = await apiReq.get(debugURLs.lastRecipe);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getIsDemo() {
|
||||
const response = await apiReq.get(debugURLs.demo);
|
||||
const response = await apiReq.get(API_ROUTES.debugLastRecipeJson);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getStatistics() {
|
||||
const response = await apiReq.get(debugURLs.statistics);
|
||||
const response = await apiReq.get(API_ROUTES.debugStatistics);
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,25 +1,16 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import { store } from "../store";
|
||||
import i18n from "@/i18n.js";
|
||||
|
||||
const migrationBase = baseURL + "migrations";
|
||||
|
||||
const migrationURLs = {
|
||||
// New
|
||||
all: migrationBase,
|
||||
delete: (folder, file) => `${migrationBase}/${folder}/${file}/delete`,
|
||||
import: (folder, file) => `${migrationBase}/${folder}/${file}/import`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
export const migrationAPI = {
|
||||
async getMigrations() {
|
||||
let response = await apiReq.get(migrationURLs.all);
|
||||
let response = await apiReq.get(API_ROUTES.migrations);
|
||||
return response.data;
|
||||
},
|
||||
async delete(folder, file) {
|
||||
const response = await apiReq.delete(
|
||||
migrationURLs.delete(folder, file),
|
||||
API_ROUTES.migrationsImportTypeFileNameDelete(folder, file),
|
||||
null,
|
||||
() => i18n.t("general.file-folder-not-found"),
|
||||
() => i18n.t("migration.migration-data-removed")
|
||||
|
@ -27,7 +18,7 @@ export const migrationAPI = {
|
|||
return response;
|
||||
},
|
||||
async import(folder, file) {
|
||||
let response = await apiReq.post(migrationURLs.import(folder, file));
|
||||
let response = await apiReq.post(API_ROUTES.migrationsImportTypeFileNameImport(folder, file));
|
||||
store.dispatch("requestRecentRecipes");
|
||||
return response.data;
|
||||
},
|
||||
|
|
|
@ -1,28 +1,8 @@
|
|||
import { API_ROUTES } from "./apiRoutes";
|
||||
import { apiReq } from "./api-utils";
|
||||
import { baseURL } from "./api-utils";
|
||||
import { store } from "../store";
|
||||
import i18n from "@/i18n.js";
|
||||
|
||||
const prefix = baseURL + "recipes/";
|
||||
|
||||
const recipeURLs = {
|
||||
allRecipes: baseURL + "recipes",
|
||||
summary: baseURL + "recipes" + "/summary",
|
||||
allRecipesByCategory: prefix + "category",
|
||||
create: prefix + "create",
|
||||
createByURL: prefix + "create-url",
|
||||
testParseURL: prefix + "test-scrape-url",
|
||||
recipe: slug => prefix + slug,
|
||||
update: slug => prefix + slug,
|
||||
delete: slug => prefix + slug,
|
||||
createAsset: slug => `${prefix}${slug}/assets`,
|
||||
recipeImage: slug => `${prefix}${slug}/image`,
|
||||
updateImage: slug => `${prefix}${slug}/image`,
|
||||
untagged: prefix + "summary/untagged",
|
||||
uncategorized: prefix + "summary/uncategorized ",
|
||||
};
|
||||
|
||||
export const recipeAPI = {
|
||||
/**
|
||||
* Create a Recipe by URL
|
||||
|
@ -30,7 +10,7 @@ export const recipeAPI = {
|
|||
* @returns {string} Recipe Slug
|
||||
*/
|
||||
async createByURL(recipeURL) {
|
||||
const response = await apiReq.post(recipeURLs.createByURL, { url: recipeURL }, false, () =>
|
||||
const response = await apiReq.post(API_ROUTES.recipesCreateUrl, { url: recipeURL }, false, () =>
|
||||
i18n.t("recipe.recipe-created")
|
||||
);
|
||||
|
||||
|
@ -39,13 +19,13 @@ export const recipeAPI = {
|
|||
},
|
||||
|
||||
async getAllByCategory(categories) {
|
||||
let response = await apiReq.post(recipeURLs.allRecipesByCategory, categories);
|
||||
let response = await apiReq.post(API_ROUTES.recipesCategory, categories);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async create(recipeData) {
|
||||
const response = await apiReq.post(
|
||||
recipeURLs.create,
|
||||
API_ROUTES.recipesCreate,
|
||||
recipeData,
|
||||
() => i18n.t("recipe.recipe-creation-failed"),
|
||||
() => i18n.t("recipe.recipe-created")
|
||||
|
@ -55,7 +35,7 @@ export const recipeAPI = {
|
|||
},
|
||||
|
||||
async requestDetails(recipeSlug) {
|
||||
let response = await apiReq.get(recipeURLs.recipe(recipeSlug));
|
||||
let response = await apiReq.get(API_ROUTES.recipesRecipeSlug(recipeSlug));
|
||||
return response.data;
|
||||
},
|
||||
|
||||
|
@ -72,7 +52,7 @@ export const recipeAPI = {
|
|||
}
|
||||
|
||||
return apiReq.put(
|
||||
recipeURLs.updateImage(recipeSlug),
|
||||
API_ROUTES.recipesRecipeSlugImage(recipeSlug),
|
||||
formData,
|
||||
() => i18n.t("general.image-upload-failed"),
|
||||
successMessage
|
||||
|
@ -85,13 +65,13 @@ export const recipeAPI = {
|
|||
fd.append("extension", fileObject.name.split(".").pop());
|
||||
fd.append("name", name);
|
||||
fd.append("icon", icon);
|
||||
const response = apiReq.post(recipeURLs.createAsset(recipeSlug), fd);
|
||||
const response = apiReq.post(API_ROUTES.recipesRecipeSlugAssets(recipeSlug), fd);
|
||||
return response;
|
||||
},
|
||||
|
||||
updateImagebyURL(slug, url) {
|
||||
return apiReq.post(
|
||||
recipeURLs.updateImage(slug),
|
||||
API_ROUTES.recipesRecipeSlugImage(slug),
|
||||
{ url: url },
|
||||
() => i18n.t("general.image-upload-failed"),
|
||||
() => i18n.t("recipe.recipe-image-updated")
|
||||
|
@ -100,7 +80,7 @@ export const recipeAPI = {
|
|||
|
||||
async update(data) {
|
||||
let response = await apiReq.put(
|
||||
recipeURLs.update(data.slug),
|
||||
API_ROUTES.recipesRecipeSlug(data.slug),
|
||||
data,
|
||||
() => i18n.t("recipe.recipe-update-failed"),
|
||||
() => i18n.t("recipe.recipe-updated")
|
||||
|
@ -112,14 +92,14 @@ export const recipeAPI = {
|
|||
},
|
||||
|
||||
async patch(data) {
|
||||
let response = await apiReq.patch(recipeURLs.update(data.slug), data);
|
||||
let response = await apiReq.patch(API_ROUTES.recipesRecipeSlug(data.slug), data);
|
||||
store.dispatch("patchRecipe", response.data);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async delete(recipeSlug) {
|
||||
const response = await apiReq.delete(
|
||||
recipeURLs.delete(recipeSlug),
|
||||
API_ROUTES.recipesRecipeSlug(recipeSlug),
|
||||
null,
|
||||
() => i18n.t("recipe.unable-to-delete-recipe"),
|
||||
() => i18n.t("recipe.recipe-deleted")
|
||||
|
@ -129,19 +109,19 @@ export const recipeAPI = {
|
|||
},
|
||||
|
||||
async allSummary(start = 0, limit = 9999) {
|
||||
const response = await apiReq.get(recipeURLs.summary, {
|
||||
const response = await apiReq.get(API_ROUTES.recipesSummary, {
|
||||
params: { start: start, limit: limit },
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async allUntagged() {
|
||||
const response = await apiReq.get(recipeURLs.untagged);
|
||||
const response = await apiReq.get(API_ROUTES.recipesSummaryUntagged);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async allUnategorized() {
|
||||
const response = await apiReq.get(recipeURLs.uncategorized);
|
||||
const response = await apiReq.get(API_ROUTES.recipesSummaryUncategorized);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
|
@ -186,7 +166,7 @@ export const recipeAPI = {
|
|||
},
|
||||
|
||||
async testScrapeURL(url) {
|
||||
const response = await apiReq.post(recipeURLs.testParseURL, { url: url });
|
||||
const response = await apiReq.post(API_ROUTES.recipesTestScrapeUrl, { url: url });
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,27 +1,19 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
|
||||
const settingsBase = baseURL + "site-settings";
|
||||
|
||||
const settingsURLs = {
|
||||
siteSettings: `${settingsBase}`,
|
||||
updateSiteSettings: `${settingsBase}`,
|
||||
testWebhooks: `${settingsBase}/webhooks/test`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
export const settingsAPI = {
|
||||
async requestAll() {
|
||||
let response = await apiReq.get(settingsURLs.siteSettings);
|
||||
let response = await apiReq.get(API_ROUTES.siteSettings);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async testWebhooks() {
|
||||
let response = await apiReq.post(settingsURLs.testWebhooks);
|
||||
let response = await apiReq.post(API_ROUTES.siteSettingsWebhooksTest);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async update(body) {
|
||||
let response = await apiReq.put(settingsURLs.updateSiteSettings, body);
|
||||
let response = await apiReq.put(API_ROUTES.siteSettings, body);
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,24 +1,15 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import i18n from "@/i18n.js";
|
||||
|
||||
const signUpPrefix = baseURL + "users/sign-ups";
|
||||
|
||||
const signUpURLs = {
|
||||
all: `${signUpPrefix}`,
|
||||
createToken: `${signUpPrefix}`,
|
||||
deleteToken: token => `${signUpPrefix}/${token}`,
|
||||
createUser: token => `${signUpPrefix}/${token}`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
export const signupAPI = {
|
||||
async getAll() {
|
||||
let response = await apiReq.get(signUpURLs.all);
|
||||
let response = await apiReq.get(API_ROUTES.usersSignUps);
|
||||
return response.data;
|
||||
},
|
||||
async createToken(data) {
|
||||
let response = await apiReq.post(
|
||||
signUpURLs.createToken,
|
||||
API_ROUTES.usersSignUps,
|
||||
data,
|
||||
() => i18n.t("signup.sign-up-link-creation-failed"),
|
||||
() => i18n.t("signup.sign-up-link-created")
|
||||
|
@ -27,7 +18,7 @@ export const signupAPI = {
|
|||
},
|
||||
async deleteToken(token) {
|
||||
return await apiReq.delete(
|
||||
signUpURLs.deleteToken(token),
|
||||
API_ROUTES.usersSignUpsToken(token),
|
||||
null,
|
||||
() => i18n.t("signup.sign-up-token-deletion-failed"),
|
||||
() => i18n.t("signup.sign-up-token-deleted")
|
||||
|
@ -35,7 +26,7 @@ export const signupAPI = {
|
|||
},
|
||||
async createUser(token, data) {
|
||||
return apiReq.post(
|
||||
signUpURLs.createUser(token),
|
||||
API_ROUTES.usersSignUpsToken(token),
|
||||
data,
|
||||
() => i18n.t("user.you-are-not-allowed-to-create-a-user"),
|
||||
() => i18n.t("user.user-created")
|
||||
|
|
|
@ -1,27 +1,17 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import { store } from "@/store";
|
||||
import i18n from "@/i18n.js";
|
||||
|
||||
const settingsBase = baseURL + "site-settings";
|
||||
|
||||
const settingsURLs = {
|
||||
siteSettings: `${settingsBase}`,
|
||||
updateSiteSettings: `${settingsBase}`,
|
||||
testWebhooks: `${settingsBase}/webhooks/test`,
|
||||
customPages: `${settingsBase}/custom-pages`,
|
||||
customPage: id => `${settingsBase}/custom-pages/${id}`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
export const siteSettingsAPI = {
|
||||
async get() {
|
||||
let response = await apiReq.get(settingsURLs.siteSettings);
|
||||
let response = await apiReq.get(API_ROUTES.siteSettings);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async update(body) {
|
||||
const response = await apiReq.put(
|
||||
settingsURLs.updateSiteSettings,
|
||||
API_ROUTES.siteSettings,
|
||||
body,
|
||||
() => i18n.t("settings.settings-update-failed"),
|
||||
() => i18n.t("settings.settings-updated")
|
||||
|
@ -33,18 +23,18 @@ export const siteSettingsAPI = {
|
|||
},
|
||||
|
||||
async getPages() {
|
||||
let response = await apiReq.get(settingsURLs.customPages);
|
||||
let response = await apiReq.get(API_ROUTES.siteSettingsCustomPages);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getPage(id) {
|
||||
let response = await apiReq.get(settingsURLs.customPage(id));
|
||||
let response = await apiReq.get(API_ROUTES.siteSettingsCustomPagesId(id));
|
||||
return response.data;
|
||||
},
|
||||
|
||||
createPage(body) {
|
||||
return apiReq.post(
|
||||
settingsURLs.customPages,
|
||||
API_ROUTES.siteSettingsCustomPages,
|
||||
body,
|
||||
() => i18n.t("page.page-creation-failed"),
|
||||
() => i18n.t("page.new-page-created")
|
||||
|
@ -53,7 +43,7 @@ export const siteSettingsAPI = {
|
|||
|
||||
async deletePage(id) {
|
||||
return await apiReq.delete(
|
||||
settingsURLs.customPage(id),
|
||||
API_ROUTES.siteSettingsCustomPagesId(id),
|
||||
null,
|
||||
() => i18n.t("page.page-deletion-failed"),
|
||||
() => i18n.t("page.page-deleted")
|
||||
|
@ -62,7 +52,7 @@ export const siteSettingsAPI = {
|
|||
|
||||
updatePage(body) {
|
||||
return apiReq.put(
|
||||
settingsURLs.customPage(body.id),
|
||||
API_ROUTES.siteSettingsCustomPagesId(body.id),
|
||||
body,
|
||||
() => i18n.t("page.page-update-failed"),
|
||||
() => i18n.t("page.page-updated")
|
||||
|
@ -71,7 +61,7 @@ export const siteSettingsAPI = {
|
|||
|
||||
async updateAllPages(allPages) {
|
||||
let response = await apiReq.put(
|
||||
settingsURLs.customPages,
|
||||
API_ROUTES.siteSettingsCustomPages,
|
||||
allPages,
|
||||
() => i18n.t("page.pages-update-failed"),
|
||||
() => i18n.t("page.pages-updated")
|
||||
|
|
|
@ -1,31 +1,21 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import i18n from "@/i18n.js";
|
||||
|
||||
const prefix = baseURL + "themes";
|
||||
|
||||
const settingsURLs = {
|
||||
allThemes: `${baseURL}themes`,
|
||||
specificTheme: id => `${prefix}/${id}`,
|
||||
createTheme: `${prefix}/create`,
|
||||
updateTheme: id => `${prefix}/${id}`,
|
||||
deleteTheme: id => `${prefix}/${id}`,
|
||||
};
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
|
||||
export const themeAPI = {
|
||||
async requestAll() {
|
||||
let response = await apiReq.get(settingsURLs.allThemes);
|
||||
let response = await apiReq.get(API_ROUTES.themes);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async requestByName(name) {
|
||||
let response = await apiReq.get(settingsURLs.specificTheme(name));
|
||||
let response = await apiReq.get(API_ROUTES.themesId(name));
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async create(postBody) {
|
||||
return await apiReq.post(
|
||||
settingsURLs.createTheme,
|
||||
API_ROUTES.themesCreate,
|
||||
postBody,
|
||||
() => i18n.t("settings.theme.error-creating-theme-see-log-file"),
|
||||
() => i18n.t("settings.theme.theme-saved")
|
||||
|
@ -34,7 +24,7 @@ export const themeAPI = {
|
|||
|
||||
update(data) {
|
||||
return apiReq.put(
|
||||
settingsURLs.updateTheme(data.id),
|
||||
API_ROUTES.themesId(data.id),
|
||||
data,
|
||||
() => i18n.t("settings.theme.error-updating-theme"),
|
||||
() => i18n.t("settings.theme.theme-updated")
|
||||
|
@ -43,7 +33,7 @@ export const themeAPI = {
|
|||
|
||||
delete(id) {
|
||||
return apiReq.delete(
|
||||
settingsURLs.deleteTheme(id),
|
||||
API_ROUTES.themesId(id),
|
||||
null,
|
||||
() => i18n.t("settings.theme.error-deleting-theme"),
|
||||
() => i18n.t("settings.theme.theme-deleted")
|
||||
|
|
|
@ -1,62 +1,44 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { API_ROUTES } from "./apiRoutes";
|
||||
import { apiReq } from "./api-utils";
|
||||
import axios from "axios";
|
||||
import i18n from "@/i18n.js";
|
||||
const authPrefix = baseURL + "auth";
|
||||
const userPrefix = baseURL + "users";
|
||||
|
||||
const authURLs = {
|
||||
token: `${authPrefix}/token`,
|
||||
refresh: `${authPrefix}/refresh`,
|
||||
};
|
||||
|
||||
const usersURLs = {
|
||||
users: `${userPrefix}`,
|
||||
self: `${userPrefix}/self`,
|
||||
userID: id => `${userPrefix}/${id}`,
|
||||
password: id => `${userPrefix}/${id}/password`,
|
||||
resetPassword: id => `${userPrefix}/${id}/reset-password`,
|
||||
userAPICreate: `${userPrefix}/api-tokens`,
|
||||
userAPIDelete: id => `${userPrefix}/api-tokens/${id}`,
|
||||
};
|
||||
|
||||
export const userAPI = {
|
||||
async login(formData) {
|
||||
let response = await apiReq.post(authURLs.token, formData, null, function() {
|
||||
let response = await apiReq.post(API_ROUTES.authToken, formData, null, function() {
|
||||
return i18n.t("user.user-successfully-logged-in");
|
||||
});
|
||||
return response;
|
||||
},
|
||||
async refresh() {
|
||||
let response = await axios.get(authURLs.refresh).catch(function(event) {
|
||||
let response = await axios.get(API_ROUTES.authRefresh).catch(function(event) {
|
||||
console.log("Fetch failed", event);
|
||||
});
|
||||
return response.data ? response.data : false;
|
||||
},
|
||||
async allUsers() {
|
||||
let response = await apiReq.get(usersURLs.users);
|
||||
let response = await apiReq.get(API_ROUTES.users);
|
||||
return response.data;
|
||||
},
|
||||
create(user) {
|
||||
return apiReq.post(
|
||||
usersURLs.users,
|
||||
API_ROUTES.users,
|
||||
user,
|
||||
() => i18n.t("user.user-creation-failed"),
|
||||
() => i18n.t("user.user-created")
|
||||
);
|
||||
},
|
||||
async self() {
|
||||
let response = await apiReq.get(usersURLs.self);
|
||||
let response = await apiReq.get(API_ROUTES.usersSelf);
|
||||
return response.data;
|
||||
},
|
||||
async byID(id) {
|
||||
let response = await apiReq.get(usersURLs.userID(id));
|
||||
let response = await apiReq.get(API_ROUTES.usersId(id));
|
||||
return response.data;
|
||||
},
|
||||
update(user) {
|
||||
return apiReq.put(
|
||||
usersURLs.userID(user.id),
|
||||
API_ROUTES.usersId(user.id),
|
||||
user,
|
||||
() => i18n.t("user.user-update-failed"),
|
||||
() => i18n.t("user.user-updated")
|
||||
|
@ -64,7 +46,7 @@ export const userAPI = {
|
|||
},
|
||||
changePassword(id, password) {
|
||||
return apiReq.put(
|
||||
usersURLs.password(id),
|
||||
API_ROUTES.usersIdPassword(id),
|
||||
password,
|
||||
() => i18n.t("user.existing-password-does-not-match"),
|
||||
() => i18n.t("user.password-updated")
|
||||
|
@ -72,24 +54,24 @@ export const userAPI = {
|
|||
},
|
||||
|
||||
delete(id) {
|
||||
return apiReq.delete(usersURLs.userID(id), null, deleteErrorText, () => {
|
||||
return apiReq.delete(API_ROUTES.usersId(id), null, deleteErrorText, () => {
|
||||
return i18n.t("user.user-deleted");
|
||||
});
|
||||
},
|
||||
resetPassword(id) {
|
||||
return apiReq.put(
|
||||
usersURLs.resetPassword(id),
|
||||
API_ROUTES.usersIdResetPassword(id),
|
||||
null,
|
||||
() => i18n.t("user.password-reset-failed"),
|
||||
() => i18n.t("user.password-has-been-reset-to-the-default-password")
|
||||
);
|
||||
},
|
||||
async createAPIToken(name) {
|
||||
const response = await apiReq.post(usersURLs.userAPICreate, { name });
|
||||
const response = await apiReq.post(API_ROUTES.usersApiTokens, { name });
|
||||
return response.data;
|
||||
},
|
||||
async deleteAPIToken(id) {
|
||||
const response = await apiReq.delete(usersURLs.userAPIDelete(id));
|
||||
const response = await apiReq.delete(API_ROUTES.usersApiTokensTokenId(id));
|
||||
return response.data;
|
||||
},
|
||||
/** Adds a Recipe to the users favorites
|
||||
|
|
|
@ -44,7 +44,7 @@ import { api } from "@/api";
|
|||
import BaseDialog from "./BaseDialog";
|
||||
import ImportOptions from "@/components/FormHelpers/ImportOptions";
|
||||
import TheDownloadBtn from "@/components/UI/Buttons/TheDownloadBtn.vue";
|
||||
import { backupURLs } from "@/api/backup";
|
||||
import { API_ROUTES } from "@/api/apiRoutes";
|
||||
export default {
|
||||
components: { ImportOptions, TheDownloadBtn, BaseDialog },
|
||||
props: {
|
||||
|
@ -73,7 +73,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
downloadUrl() {
|
||||
return backupURLs.downloadBackup(this.name);
|
||||
return API_ROUTES.backupsFileNameDownload(this.name);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { globals } from "@/utils/globals";
|
|||
import i18n from "./i18n";
|
||||
import "@mdi/font/css/materialdesignicons.css";
|
||||
import "typeface-roboto/index.css";
|
||||
import './registerServiceWorker'
|
||||
import "./registerServiceWorker";
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
Vue.use(VueRouter);
|
||||
|
|
|
@ -23,12 +23,3 @@ const icons = {
|
|||
export const globals = {
|
||||
icons,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
import { globals } from "@/utils/globals"
|
||||
globals: globals,
|
||||
|
||||
{{ globals.icons. }}
|
||||
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue