Merge branch 'develop' into feature/unit-conversion
# Conflicts: # vue/src/components/Modals/GenericModalForm.vue
This commit is contained in:
@ -3,6 +3,9 @@
|
|||||||
DEBUG=0
|
DEBUG=0
|
||||||
SQL_DEBUG=0
|
SQL_DEBUG=0
|
||||||
DEBUG_TOOLBAR=0
|
DEBUG_TOOLBAR=0
|
||||||
|
# Gunicorn log level for debugging (default value is "info" when unset)
|
||||||
|
# (see https://docs.gunicorn.org/en/stable/settings.html#loglevel for available settings)
|
||||||
|
# GUNICORN_LOG_LEVEL="debug"
|
||||||
|
|
||||||
# HTTP port to bind to
|
# HTTP port to bind to
|
||||||
# TANDOOR_PORT=8080
|
# TANDOOR_PORT=8080
|
||||||
|
120
.github/workflows/build-docker-open-data.yml
vendored
Normal file
120
.github/workflows/build-docker-open-data.yml
vendored
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
name: Build Docker Container with open data plugin installed
|
||||||
|
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-container:
|
||||||
|
name: Build ${{ matrix.name }} Container
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.repository_owner == 'TandoorRecipes'
|
||||||
|
continue-on-error: ${{ matrix.continue-on-error }}
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
# Standard build config
|
||||||
|
- name: Standard
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
suffix: ""
|
||||||
|
continue-on-error: false
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Get version number
|
||||||
|
id: get_version
|
||||||
|
run: |
|
||||||
|
if [[ "$GITHUB_REF" = refs/tags/* ]]; then
|
||||||
|
echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT
|
||||||
|
elif [[ "$GITHUB_REF" = refs/heads/beta ]]; then
|
||||||
|
echo VERSION=beta >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo VERSION=develop >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update Version number
|
||||||
|
- name: Update version file
|
||||||
|
uses: DamianReeves/write-file-action@v1.2
|
||||||
|
with:
|
||||||
|
path: recipes/version.py
|
||||||
|
contents: |
|
||||||
|
VERSION_NUMBER = '${{ steps.get_version.outputs.VERSION }}-open-data'
|
||||||
|
BUILD_REF = '${{ github.sha }}'
|
||||||
|
write-mode: overwrite
|
||||||
|
|
||||||
|
# clone open data plugin
|
||||||
|
- name: clone open data plugin repo
|
||||||
|
uses: actions/checkout@master
|
||||||
|
with:
|
||||||
|
repository: TandoorRecipes/open_data_plugin
|
||||||
|
ref: master
|
||||||
|
path: ./recipes/plugins/open_data_plugin
|
||||||
|
|
||||||
|
# Build Vue frontend
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: '14'
|
||||||
|
cache: yarn
|
||||||
|
cache-dependency-path: vue/yarn.lock
|
||||||
|
- name: Install dependencies
|
||||||
|
working-directory: ./vue
|
||||||
|
run: yarn install --frozen-lockfile
|
||||||
|
- name: Build dependencies
|
||||||
|
working-directory: ./vue
|
||||||
|
run: yarn build
|
||||||
|
|
||||||
|
- name: Setup Open Data Plugin Links
|
||||||
|
working-directory: ./recipes/plugins/open_data_plugin
|
||||||
|
run: python setup_repo.py
|
||||||
|
|
||||||
|
- name: Build Open Data Frontend
|
||||||
|
working-directory: ./recipes/plugins/open_data_plugin/vue
|
||||||
|
run: yarn build
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
- name: Set up Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
if: github.secret_source == 'Actions'
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
if: github.secret_source == 'Actions'
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ github.token }}
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
vabene1111/recipes
|
||||||
|
ghcr.io/TandoorRecipes/recipes
|
||||||
|
flavor: |
|
||||||
|
latest=false
|
||||||
|
suffix=${{ matrix.suffix }}
|
||||||
|
tags: |
|
||||||
|
type=raw,value=latest,suffix=-open-data-plugin,enable=${{ startsWith(github.ref, 'refs/tags/') }}
|
||||||
|
type=semver,suffix=-open-data-plugin,pattern={{version}}
|
||||||
|
type=semver,suffix=-open-data-plugin,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,suffix=-open-data-plugin,pattern={{major}}
|
||||||
|
type=ref,suffix=-open-data-plugin,event=branch
|
||||||
|
- name: Build and Push
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ${{ matrix.dockerfile }}
|
||||||
|
pull: true
|
||||||
|
push: ${{ github.secret_source == 'Actions' }}
|
||||||
|
platforms: ${{ matrix.platforms }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
3
boot.sh
3
boot.sh
@ -4,6 +4,7 @@ source venv/bin/activate
|
|||||||
TANDOOR_PORT="${TANDOOR_PORT:-8080}"
|
TANDOOR_PORT="${TANDOOR_PORT:-8080}"
|
||||||
GUNICORN_WORKERS="${GUNICORN_WORKERS:-3}"
|
GUNICORN_WORKERS="${GUNICORN_WORKERS:-3}"
|
||||||
GUNICORN_THREADS="${GUNICORN_THREADS:-2}"
|
GUNICORN_THREADS="${GUNICORN_THREADS:-2}"
|
||||||
|
GUNICORN_LOG_LEVEL="${GUNICORN_LOG_LEVEL:-'info'}"
|
||||||
NGINX_CONF_FILE=/opt/recipes/nginx/conf.d/Recipes.conf
|
NGINX_CONF_FILE=/opt/recipes/nginx/conf.d/Recipes.conf
|
||||||
|
|
||||||
display_warning() {
|
display_warning() {
|
||||||
@ -65,4 +66,4 @@ echo "Done"
|
|||||||
|
|
||||||
chmod -R 755 /opt/recipes/mediafiles
|
chmod -R 755 /opt/recipes/mediafiles
|
||||||
|
|
||||||
exec gunicorn -b :$TANDOOR_PORT --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --access-logfile - --error-logfile - --log-level INFO recipes.wsgi
|
exec gunicorn -b :$TANDOOR_PORT --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --access-logfile - --error-logfile - --log-level $GUNICORN_LOG_LEVEL recipes.wsgi
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
{% endblock %}</title>
|
{% endblock %}</title>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="robots" content="noindex,nofollow"/>
|
||||||
|
|
||||||
|
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="{% static 'assets/favicon.svg' %}">
|
<link rel="shortcut icon" type="image/x-icon" href="{% static 'assets/favicon.svg' %}">
|
||||||
@ -49,7 +50,7 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$.fn.select2.defaults.set("theme", "bootstrap");
|
$.fn.select2.defaults.set("theme", "bootstrap");
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
window.ACTIVE_SPACE_ID = '{{request.space.id}}';
|
window.ACTIVE_SPACE_ID = '{{request.space.id}}';
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -349,6 +350,12 @@
|
|||||||
<a class="dropdown-item" href="{% url 'view_space_overview' %}"><i
|
<a class="dropdown-item" href="{% url 'view_space_overview' %}"><i
|
||||||
class="fas fa-list"></i> {% trans 'Overview' %}</a>
|
class="fas fa-list"></i> {% trans 'Overview' %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% plugin_dropdown_nav_templates as plugin_dropdown_nav_templates %}
|
||||||
|
{% for pn in plugin_dropdown_nav_templates %}
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
{% include pn %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<a class="dropdown-item" href="{% url 'docs_markdown' %}"><i
|
<a class="dropdown-item" href="{% url 'docs_markdown' %}"><i
|
||||||
class="fab fa-markdown fa-fw"></i> {% trans 'Markdown Guide' %}</a>
|
class="fab fa-markdown fa-fw"></i> {% trans 'Markdown Guide' %}</a>
|
||||||
@ -375,6 +382,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
{% message_of_the_day request as message_of_the_day %}
|
{% message_of_the_day request as message_of_the_day %}
|
||||||
{% if message_of_the_day %}
|
{% if message_of_the_day %}
|
||||||
<div class="bg-info" style=" width: 100%; text-align: center!important; color: #ffffff; padding: 8px">
|
<div class="bg-info" style=" width: 100%; text-align: center!important; color: #ffffff; padding: 8px">
|
||||||
|
@ -16,7 +16,7 @@ from cookbook.helper.mdx_attributes import MarkdownFormatExtension
|
|||||||
from cookbook.helper.mdx_urlize import UrlizeExtension
|
from cookbook.helper.mdx_urlize import UrlizeExtension
|
||||||
from cookbook.models import Space, get_model_name
|
from cookbook.models import Space, get_model_name
|
||||||
from recipes import settings
|
from recipes import settings
|
||||||
from recipes.settings import STATIC_URL
|
from recipes.settings import STATIC_URL, PLUGINS
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
@ -132,6 +132,14 @@ def is_debug():
|
|||||||
def markdown_link():
|
def markdown_link():
|
||||||
return f"{_('You can use markdown to format this field. See the ')}<a target='_blank' href='{reverse('docs_markdown')}'>{_('docs here')}</a>"
|
return f"{_('You can use markdown to format this field. See the ')}<a target='_blank' href='{reverse('docs_markdown')}'>{_('docs here')}</a>"
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def plugin_dropdown_nav_templates():
|
||||||
|
templates = []
|
||||||
|
for p in PLUGINS:
|
||||||
|
if p['nav_dropdown']:
|
||||||
|
templates.append(p['nav_dropdown'])
|
||||||
|
return templates
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def bookmarklet(request):
|
def bookmarklet(request):
|
||||||
|
@ -6,7 +6,7 @@ from rest_framework import permissions, routers
|
|||||||
from rest_framework.schemas import get_schema_view
|
from rest_framework.schemas import get_schema_view
|
||||||
|
|
||||||
from cookbook.helper import dal
|
from cookbook.helper import dal
|
||||||
from recipes.settings import DEBUG
|
from recipes.settings import DEBUG, PLUGINS
|
||||||
from recipes.version import VERSION_NUMBER
|
from recipes.version import VERSION_NUMBER
|
||||||
|
|
||||||
from .models import (Automation, Comment, CustomFilter, Food, InviteLink, Keyword, MealPlan, Recipe,
|
from .models import (Automation, Comment, CustomFilter, Food, InviteLink, Keyword, MealPlan, Recipe,
|
||||||
@ -16,7 +16,13 @@ from .models import (Automation, Comment, CustomFilter, Food, InviteLink, Keywor
|
|||||||
from .views import api, data, delete, edit, import_export, lists, new, telegram, views
|
from .views import api, data, delete, edit, import_export, lists, new, telegram, views
|
||||||
from .views.api import CustomAuthToken, ImportOpenData
|
from .views.api import CustomAuthToken, ImportOpenData
|
||||||
|
|
||||||
router = routers.DefaultRouter()
|
# extend DRF default router class to allow including additional routers
|
||||||
|
class DefaultRouter(routers.DefaultRouter):
|
||||||
|
def extend(self, r):
|
||||||
|
self.registry.extend(r.registry)
|
||||||
|
|
||||||
|
|
||||||
|
router = DefaultRouter()
|
||||||
router.register(r'automation', api.AutomationViewSet)
|
router.register(r'automation', api.AutomationViewSet)
|
||||||
router.register(r'bookmarklet-import', api.BookmarkletImportViewSet)
|
router.register(r'bookmarklet-import', api.BookmarkletImportViewSet)
|
||||||
router.register(r'cook-log', api.CookLogViewSet)
|
router.register(r'cook-log', api.CookLogViewSet)
|
||||||
@ -56,6 +62,13 @@ router.register(r'user-space', api.UserSpaceViewSet)
|
|||||||
router.register(r'view-log', api.ViewLogViewSet)
|
router.register(r'view-log', api.ViewLogViewSet)
|
||||||
router.register(r'access-token', api.AccessTokenViewSet)
|
router.register(r'access-token', api.AccessTokenViewSet)
|
||||||
|
|
||||||
|
for p in PLUGINS:
|
||||||
|
if c := locate(f'{p["module"]}.urls.{p["api_router_name"]}'):
|
||||||
|
try:
|
||||||
|
router.extend(c)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', views.index, name='index'),
|
path('', views.index, name='index'),
|
||||||
path('setup/', views.setup, name='view_setup'),
|
path('setup/', views.setup, name='view_setup'),
|
||||||
@ -122,7 +135,6 @@ urlpatterns = [
|
|||||||
path('api/switch-active-space/<int:space_id>/', api.switch_active_space, name='api_switch_active_space'),
|
path('api/switch-active-space/<int:space_id>/', api.switch_active_space, name='api_switch_active_space'),
|
||||||
path('api/download-file/<int:file_id>/', api.download_file, name='api_download_file'),
|
path('api/download-file/<int:file_id>/', api.download_file, name='api_download_file'),
|
||||||
|
|
||||||
|
|
||||||
path('dal/keyword/', dal.KeywordAutocomplete.as_view(), name='dal_keyword'),
|
path('dal/keyword/', dal.KeywordAutocomplete.as_view(), name='dal_keyword'),
|
||||||
# TODO is this deprecated? not yet, some old forms remain, could likely be changed to generic API endpoints
|
# TODO is this deprecated? not yet, some old forms remain, could likely be changed to generic API endpoints
|
||||||
path('dal/food/', dal.IngredientsAutocomplete.as_view(), name='dal_food'), # TODO is this deprecated?
|
path('dal/food/', dal.IngredientsAutocomplete.as_view(), name='dal_food'), # TODO is this deprecated?
|
||||||
|
@ -80,6 +80,8 @@ DJANGO_TABLES2_PAGE_RANGE = 8
|
|||||||
HCAPTCHA_SITEKEY = os.getenv('HCAPTCHA_SITEKEY', '')
|
HCAPTCHA_SITEKEY = os.getenv('HCAPTCHA_SITEKEY', '')
|
||||||
HCAPTCHA_SECRET = os.getenv('HCAPTCHA_SECRET', '')
|
HCAPTCHA_SECRET = os.getenv('HCAPTCHA_SECRET', '')
|
||||||
|
|
||||||
|
FDA_API_KEY = os.getenv('FDA_API_KEY', 'DEMO_KEY')
|
||||||
|
|
||||||
SHARING_ABUSE = bool(int(os.getenv('SHARING_ABUSE', False)))
|
SHARING_ABUSE = bool(int(os.getenv('SHARING_ABUSE', False)))
|
||||||
SHARING_LIMIT = int(os.getenv('SHARING_LIMIT', 0))
|
SHARING_LIMIT = int(os.getenv('SHARING_LIMIT', 0))
|
||||||
|
|
||||||
@ -144,6 +146,9 @@ try:
|
|||||||
'base_path': os.path.join(BASE_DIR, 'recipes', 'plugins', d),
|
'base_path': os.path.join(BASE_DIR, 'recipes', 'plugins', d),
|
||||||
'base_url': plugin_class.base_url,
|
'base_url': plugin_class.base_url,
|
||||||
'bundle_name': plugin_class.bundle_name if hasattr(plugin_class, 'bundle_name') else '',
|
'bundle_name': plugin_class.bundle_name if hasattr(plugin_class, 'bundle_name') else '',
|
||||||
|
'api_router_name': plugin_class.api_router_name if hasattr(plugin_class, 'api_router_name') else '',
|
||||||
|
'nav_main': plugin_class.nav_main if hasattr(plugin_class, 'nav_main') else '',
|
||||||
|
'nav_dropdown': plugin_class.nav_dropdown if hasattr(plugin_class, 'nav_dropdown') else '',
|
||||||
}
|
}
|
||||||
PLUGINS.append(plugin_config)
|
PLUGINS.append(plugin_config)
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -412,7 +417,7 @@ for p in PLUGINS:
|
|||||||
if p['bundle_name'] != '':
|
if p['bundle_name'] != '':
|
||||||
WEBPACK_LOADER[p['bundle_name']] = {
|
WEBPACK_LOADER[p['bundle_name']] = {
|
||||||
'CACHE': not DEBUG,
|
'CACHE': not DEBUG,
|
||||||
'BUNDLE_DIR_NAME': f'{p["base_path"]}/vue/', # must end with slash
|
'BUNDLE_DIR_NAME': f'vue/', # must end with slash
|
||||||
'STATS_FILE': os.path.join(p["base_path"], 'vue', 'webpack-stats.json'),
|
'STATS_FILE': os.path.join(p["base_path"], 'vue', 'webpack-stats.json'),
|
||||||
'POLL_INTERVAL': 0.1,
|
'POLL_INTERVAL': 0.1,
|
||||||
'TIMEOUT': None,
|
'TIMEOUT': None,
|
||||||
|
@ -17,7 +17,7 @@ Markdown==3.4.3
|
|||||||
Pillow==9.4.0
|
Pillow==9.4.0
|
||||||
psycopg2-binary==2.9.5
|
psycopg2-binary==2.9.5
|
||||||
python-dotenv==0.21.0
|
python-dotenv==0.21.0
|
||||||
requests==2.28.2
|
requests==2.31.0
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
webdavclient3==3.14.6
|
webdavclient3==3.14.6
|
||||||
whitenoise==6.2.0
|
whitenoise==6.2.0
|
||||||
|
@ -109,6 +109,10 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.id = Math.random()
|
this.id = Math.random()
|
||||||
this.$root.$on("change", this.storeValue) // bootstrap modal placed at document so have to listen at root of component
|
this.$root.$on("change", this.storeValue) // bootstrap modal placed at document so have to listen at root of component
|
||||||
|
|
||||||
|
if (this.models !== null){
|
||||||
|
this.Models = this.models // override models definition file with prop
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
advancedForm() {
|
advancedForm() {
|
||||||
@ -179,6 +183,7 @@ export default {
|
|||||||
if (this.dirty) {
|
if (this.dirty) {
|
||||||
this.dirty = false
|
this.dirty = false
|
||||||
this.$emit("finish-action", "cancel")
|
this.$emit("finish-action", "cancel")
|
||||||
|
this.$emit("hidden")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
storeValue: function (field, value) {
|
storeValue: function (field, value) {
|
||||||
|
0
vue/src/stores/GenericApiStore.js
Normal file
0
vue/src/stores/GenericApiStore.js
Normal file
@ -50,7 +50,7 @@ export class StandardToasts {
|
|||||||
static FAIL_MOVE = "FAIL_MOVE"
|
static FAIL_MOVE = "FAIL_MOVE"
|
||||||
static FAIL_MERGE = "FAIL_MERGE"
|
static FAIL_MERGE = "FAIL_MERGE"
|
||||||
|
|
||||||
static makeStandardToast(context, toast, err) {
|
static makeStandardToast(context, toast, err = undefined, always_show_errors = false) {
|
||||||
let title = ''
|
let title = ''
|
||||||
let msg = ''
|
let msg = ''
|
||||||
let variant = ''
|
let variant = ''
|
||||||
@ -124,7 +124,7 @@ export class StandardToasts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let DEBUG = localStorage.getItem("DEBUG") === "True" || false
|
let DEBUG = localStorage.getItem("DEBUG") === "True" || always_show_errors
|
||||||
|
|
||||||
if (err !== undefined && 'response' in err && 'headers' in err.response) {
|
if (err !== undefined && 'response' in err && 'headers' in err.response) {
|
||||||
if (DEBUG && err.response.headers['content-type'] === 'application/json' && err.response.status < 500) {
|
if (DEBUG && err.response.headers['content-type'] === 'application/json' && err.response.status < 500) {
|
||||||
@ -311,7 +311,7 @@ export function calculateHourMinuteSplit(amount) {
|
|||||||
let minutes = amount - hours * 60
|
let minutes = amount - hours * 60
|
||||||
let output_text = hours + " h"
|
let output_text = hours + " h"
|
||||||
|
|
||||||
if (minutes > 0){
|
if (minutes > 0) {
|
||||||
output_text += " " + minutes + " min"
|
output_text += " " + minutes + " min"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,6 +368,9 @@ export const ApiMixin = {
|
|||||||
let func = setup.function
|
let func = setup.function
|
||||||
let parameters = buildParams(options, setup)
|
let parameters = buildParams(options, setup)
|
||||||
let apiClient = new ApiApiFactory()
|
let apiClient = new ApiApiFactory()
|
||||||
|
if (model.apiClient !== undefined) {
|
||||||
|
apiClient = model.apiClient
|
||||||
|
}
|
||||||
return apiClient[func](...parameters)
|
return apiClient[func](...parameters)
|
||||||
},
|
},
|
||||||
genericGetAPI: function (url, options) {
|
genericGetAPI: function (url, options) {
|
||||||
|
Reference in New Issue
Block a user