mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 03:26:45 +00:00
[UI] Add CUI compatibility URLs (#9541)
* Add CUI compatibility URLs * Add config option to enable URL compatibility * Add unit tests * Simplify tests
This commit is contained in:
parent
1dae1bc906
commit
7d87b8b896
@ -484,4 +484,13 @@ def get_frontend_settings(debug=True):
|
|||||||
# If no servers are specified, show server selector
|
# If no servers are specified, show server selector
|
||||||
frontend_settings['show_server_selector'] = True
|
frontend_settings['show_server_selector'] = True
|
||||||
|
|
||||||
|
# Support compatibility with "legacy" URLs?
|
||||||
|
try:
|
||||||
|
frontend_settings['url_compatibility'] = bool(
|
||||||
|
frontend_settings.get('url_compatibility', True)
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
# If the value is not a boolean, set it to True
|
||||||
|
frontend_settings['url_compatibility'] = True
|
||||||
|
|
||||||
return frontend_settings
|
return frontend_settings
|
||||||
|
@ -1704,3 +1704,22 @@ class SchemaPostprocessingTest(TestCase):
|
|||||||
self.assertNotIn('customer_detail', schemas_out.get('SalesOrder')['required'])
|
self.assertNotIn('customer_detail', schemas_out.get('SalesOrder')['required'])
|
||||||
# required key removed when empty
|
# required key removed when empty
|
||||||
self.assertNotIn('required', schemas_out.get('SalesOrderShipment'))
|
self.assertNotIn('required', schemas_out.get('SalesOrderShipment'))
|
||||||
|
|
||||||
|
|
||||||
|
class URLCompatibilityTest(InvenTreeTestCase):
|
||||||
|
"""Unit test for legacy URL compatibility."""
|
||||||
|
|
||||||
|
URL_MAPPINGS = [
|
||||||
|
('/index/', '/web'),
|
||||||
|
('/part/1/', '/web/part/1/'),
|
||||||
|
('/company/customers/', '/web/sales/index/customers'),
|
||||||
|
('/build/3/', '/web/manufacturing/build-order/3'),
|
||||||
|
('/stock/item/1/', '/web/stock/item/1/'),
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_legacy_urls(self):
|
||||||
|
"""Test legacy URLs."""
|
||||||
|
for old_url, new_url in self.URL_MAPPINGS:
|
||||||
|
response = self.client.get(old_url)
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
self.assertEqual(response['Location'], new_url)
|
||||||
|
@ -28,6 +28,7 @@ import report.api
|
|||||||
import stock.api
|
import stock.api
|
||||||
import users.api
|
import users.api
|
||||||
from plugin.urls import get_plugin_urls
|
from plugin.urls import get_plugin_urls
|
||||||
|
from web.urls import cui_compatibility_urls
|
||||||
from web.urls import urlpatterns as platform_urls
|
from web.urls import urlpatterns as platform_urls
|
||||||
|
|
||||||
from .api import (
|
from .api import (
|
||||||
@ -172,6 +173,10 @@ urlpatterns.append(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Compatibility layer for old (CUI) URLs
|
||||||
|
if settings.FRONTEND_SETTINGS.get('url_compatibility'):
|
||||||
|
urlpatterns += cui_compatibility_urls(settings.FRONTEND_URL_BASE)
|
||||||
|
|
||||||
# Send any unknown URLs to the index page
|
# Send any unknown URLs to the index page
|
||||||
urlpatterns += [
|
urlpatterns += [
|
||||||
re_path(
|
re_path(
|
||||||
|
@ -3,10 +3,131 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.urls import include, path, re_path
|
from django.urls import include, path, re_path
|
||||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import RedirectView, TemplateView
|
||||||
|
|
||||||
spa_view = ensure_csrf_cookie(TemplateView.as_view(template_name='web/index.html'))
|
spa_view = ensure_csrf_cookie(TemplateView.as_view(template_name='web/index.html'))
|
||||||
|
|
||||||
|
|
||||||
|
def cui_compatibility_urls(base: str) -> list:
|
||||||
|
"""Generate a list of URL patterns for compatibility with old (CUI) URLs.
|
||||||
|
|
||||||
|
These URLs are provided for backwards compatibility with older versions of InvenTree,
|
||||||
|
before we moved to a SPA (Single Page Application) architecture in the 1.0.0 release.
|
||||||
|
|
||||||
|
At some future point these may be removed?
|
||||||
|
|
||||||
|
Args:
|
||||||
|
base (str): The base URL to use for generating the patterns.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A list of URL patterns.
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
# Old 'index' view - reroute to the dashboard
|
||||||
|
path('index/', RedirectView.as_view(url=f'/{base}')),
|
||||||
|
path('settings/', RedirectView.as_view(url=f'/{base}/settings')),
|
||||||
|
# Company patterns
|
||||||
|
path(
|
||||||
|
'company/',
|
||||||
|
include([
|
||||||
|
path(
|
||||||
|
'customers/',
|
||||||
|
RedirectView.as_view(url=f'/{base}/sales/index/customers'),
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
'manufacturers/',
|
||||||
|
RedirectView.as_view(url=f'/{base}/purchasing/index/manufacturers'),
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
'suppliers/',
|
||||||
|
RedirectView.as_view(url=f'/{base}/purchasing/index/suppliers'),
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
r'(?P<pk>\d+)/', RedirectView.as_view(url=f'/{base}/company/%(pk)s')
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
# "Part" app views
|
||||||
|
re_path(
|
||||||
|
r'^part/(?P<path>.*)$', RedirectView.as_view(url=f'/{base}/part/%(path)s')
|
||||||
|
),
|
||||||
|
# "Stock" app views
|
||||||
|
re_path(
|
||||||
|
r'^stock/(?P<path>.*)$', RedirectView.as_view(url=f'/{base}/stock/%(path)s')
|
||||||
|
),
|
||||||
|
# "Build" app views (requires some custom handling)
|
||||||
|
path(
|
||||||
|
'build/',
|
||||||
|
include([
|
||||||
|
re_path(
|
||||||
|
r'^(?P<pk>\d+)/',
|
||||||
|
RedirectView.as_view(
|
||||||
|
url=f'/{base}/manufacturing/build-order/%(pk)s'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
re_path('.*', RedirectView.as_view(url=f'/{base}/manufacturing/')),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
# "Order" app views
|
||||||
|
path(
|
||||||
|
'order/',
|
||||||
|
include([
|
||||||
|
path(
|
||||||
|
'purchase-order/',
|
||||||
|
include([
|
||||||
|
re_path(
|
||||||
|
r'^(?P<pk>\d+)/',
|
||||||
|
RedirectView.as_view(
|
||||||
|
url=f'/{base}/purchasing/purchase-order/%(pk)s'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
'.*',
|
||||||
|
RedirectView.as_view(
|
||||||
|
url=f'/{base}/purchasing/index/purchaseorders/'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
'sales-order/',
|
||||||
|
include([
|
||||||
|
re_path(
|
||||||
|
r'^(?P<pk>\d+)/',
|
||||||
|
RedirectView.as_view(
|
||||||
|
url=f'/{base}/sales/sales-order/%(pk)s'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
'.*',
|
||||||
|
RedirectView.as_view(
|
||||||
|
url=f'/{base}/sales/index/salesorders/'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
'return-order/',
|
||||||
|
include([
|
||||||
|
re_path(
|
||||||
|
r'^(?P<pk>\d+)/',
|
||||||
|
RedirectView.as_view(
|
||||||
|
url=f'/{base}/sales/return-order/%(pk)s'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
'.*',
|
||||||
|
RedirectView.as_view(
|
||||||
|
url=f'/{base}/sales/index/returnorders/'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path(
|
path(
|
||||||
f'{settings.FRONTEND_URL_BASE}/',
|
f'{settings.FRONTEND_URL_BASE}/',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user