mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-16 20:15:44 +00:00
Platform UI - React integration (#5011)
* Add SPA views for react #2789 * split up frontend urls * Add settings for frontend url loading * add new UI scaffold * remove tracking insert * add platform app * ensure static indexes work too * add lingui * add lingui config * add mgmt tasks * add base locales * settings for frontend dev * fix typo * update deps * add pre-commit * add eslint * add testing scaffold * fix paths * remove error - tests trip correctly * merge workflow * cleanup samples * use name inline with other tests * Add real worl frontend tests * setup env * tun migrations first * optimize setup time * setup demo dataset * optimize run setup * add test for class ui * rename * fix typo * and another typo * do install * run migrations first * fix name * cleanup * use other credentials * use other credentials * fix qc * move envs to qc * remove create_site * reduce testing env * fix test * fix test call * allaccess user * add ui plattform check * add better check * remove unneeded env * enable debug * reduce wait time * also build frontend on static * add sort plugin * fix order * run pre-commit fixes * add node min version * Docker container (#129) * Fix allocation check for completing build order (#5199) - Allocation check only applies to untracked line items * docker dev Install required node packages to docker development image * add import order settings * cleanout built ui * remove default arg from build * remove eslint * optimize svg * add build step for plattform UI * fix install command * use alpine commands * do not use cache when creating image --------- Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
This commit is contained in:
@ -33,7 +33,7 @@ from . import config
|
||||
INVENTREE_NEWS_URL = 'https://inventree.org/news/feed.atom'
|
||||
|
||||
# Determine if we are running in "test" mode e.g. "manage.py test"
|
||||
TESTING = 'test' in sys.argv
|
||||
TESTING = 'test' in sys.argv or 'TESTING' in os.environ
|
||||
|
||||
if TESTING:
|
||||
|
||||
@ -76,6 +76,9 @@ if version_file.exists():
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = get_boolean_setting('INVENTREE_DEBUG', 'debug', True)
|
||||
|
||||
ENABLE_CLASSIC_FRONTEND = get_boolean_setting('INVENTREE_CLASSIC_FRONTEND', 'classic_frontend', True)
|
||||
ENABLE_PLATFORM_FRONTEND = get_boolean_setting('INVENTREE_PLATFORM_FRONTEND', 'platform_frontend', True)
|
||||
|
||||
# Configure logging settings
|
||||
log_level = get_setting('INVENTREE_LOG_LEVEL', 'log_level', 'WARNING')
|
||||
|
||||
@ -203,6 +206,7 @@ INSTALLED_APPS = [
|
||||
'stock.apps.StockConfig',
|
||||
'users.apps.UsersConfig',
|
||||
'plugin.apps.PluginAppConfig',
|
||||
'web',
|
||||
'generic',
|
||||
'InvenTree.apps.InvenTreeConfig', # InvenTree app runs last
|
||||
|
||||
|
@ -33,6 +33,7 @@ from report.api import report_api_urls
|
||||
from stock.api import stock_api_urls
|
||||
from stock.urls import stock_urls
|
||||
from users.api import user_urls
|
||||
from web.urls import urlpatterns as platform_urls
|
||||
|
||||
from .api import APISearchView, InfoView, NotFoundView
|
||||
from .magic_login import GetSimpleLoginView
|
||||
@ -162,7 +163,7 @@ backendpatterns = [
|
||||
re_path(r'^api-doc/', SpectacularRedocView.as_view(url_name='schema'), name='api-doc'),
|
||||
]
|
||||
|
||||
frontendpatterns = [
|
||||
classic_frontendpatterns = [
|
||||
|
||||
# Apps
|
||||
re_path(r'^build/', include(build_urls)),
|
||||
@ -205,6 +206,21 @@ frontendpatterns = [
|
||||
re_path(r'^accounts/', include('allauth.urls')), # included urlpatterns
|
||||
]
|
||||
|
||||
|
||||
new_frontendpatterns = [
|
||||
# Platform urls
|
||||
re_path(r'^platform/', include(platform_urls)),
|
||||
|
||||
]
|
||||
|
||||
# Load patterns for frontend according to settings
|
||||
frontendpatterns = []
|
||||
if settings.ENABLE_CLASSIC_FRONTEND:
|
||||
frontendpatterns.append(re_path('', include(classic_frontendpatterns)))
|
||||
if settings.ENABLE_PLATFORM_FRONTEND:
|
||||
frontendpatterns.append(re_path('', include(new_frontendpatterns)))
|
||||
|
||||
|
||||
# Append custom plugin URLs (if plugin support is enabled)
|
||||
if settings.PLUGINS_ENABLED:
|
||||
frontendpatterns.append(get_plugin_urls())
|
||||
|
@ -58,6 +58,12 @@ database:
|
||||
# Use the environment variable INVENTREE_DEBUG
|
||||
debug: True
|
||||
|
||||
# Set enabled frontends
|
||||
# Use the environment variable INVENTREE_CLASSIC_FRONTEND
|
||||
# classic_frontend: True
|
||||
# Use the environment variable INVENTREE_PLATFORM_FRONTEND
|
||||
# platform_frontend: True
|
||||
|
||||
# Configure the system logging level
|
||||
# Use environment variable INVENTREE_LOG_LEVEL
|
||||
# Options: DEBUG / INFO / WARNING / ERROR / CRITICAL
|
||||
|
18
InvenTree/web/templates/web/index.html
Normal file
18
InvenTree/web/templates/web/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
{% load spa_helper %}
|
||||
{% load inventree_extras %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{% inventree_instance_name %}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
{% spa_bundle %}
|
||||
</body>
|
||||
|
||||
</html>
|
36
InvenTree/web/templatetags/spa_helper.py
Normal file
36
InvenTree/web/templatetags/spa_helper.py
Normal file
@ -0,0 +1,36 @@
|
||||
"""Template tag to render SPA imports."""
|
||||
import json
|
||||
from logging import getLogger
|
||||
from pathlib import Path
|
||||
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
logger = getLogger("gwaesser_backend")
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def spa_bundle():
|
||||
"""Render SPA bundle."""
|
||||
manifest = Path(__file__).parent.parent.joinpath("static/web/manifest.json")
|
||||
|
||||
if not manifest.exists():
|
||||
logger.error("Manifest file not found")
|
||||
return
|
||||
|
||||
manifest_data = json.load(manifest.open())
|
||||
index = manifest_data.get("index.html")
|
||||
|
||||
dynmanic_files = index.get("dynamicImports", [])
|
||||
imports_files = "".join(
|
||||
[
|
||||
f'<script type="module" src="{settings.STATIC_URL}web/{manifest_data[file]["file"]}"></script>'
|
||||
for file in dynmanic_files
|
||||
]
|
||||
)
|
||||
|
||||
return mark_safe(
|
||||
f"""<script type="module" src="{settings.STATIC_URL}web/{index['file']}"></script>{imports_files}"""
|
||||
)
|
26
InvenTree/web/urls.py
Normal file
26
InvenTree/web/urls.py
Normal file
@ -0,0 +1,26 @@
|
||||
"""URLs for web app."""
|
||||
from django.conf import settings
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import path, re_path
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
|
||||
class RedirectAssetView(TemplateView):
|
||||
"""View to redirect to static asset."""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""Redirect to static asset."""
|
||||
return redirect(
|
||||
f"{settings.STATIC_URL}web/assets/{kwargs['path']}", permanent=True
|
||||
)
|
||||
|
||||
|
||||
spa_view = ensure_csrf_cookie(TemplateView.as_view(template_name="web/index.html"))
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("assets/<path:path>", RedirectAssetView.as_view()),
|
||||
re_path(r"^(?P<path>.*)/$", spa_view),
|
||||
path("", spa_view),
|
||||
]
|
Reference in New Issue
Block a user