Remove Vue2-based widget (#6610)

* Remove Vue2-based widget

* move floatformat.js

* Delete docready.js

* Update widget.py
This commit is contained in:
Richard Schreiber
2026-09-29 10:14:21 +02:00
committed by GitHub
parent c875d758f9
commit df74cbf5fc
9 changed files with 18 additions and 2740 deletions
File diff suppressed because one or more lines are too long
@@ -105,13 +105,6 @@ class GlobalSettingsForm(SettingsForm):
domain=settings.SITE_URL
)
)),
('widget_vue2_origins', forms.CharField(
widget=forms.Textarea(attrs={'rows': '3'}),
required=False,
# Not translated on purpose, this is a temporary feature and contains too many special case words
label="Vue2 widget origins",
help_text="One origin per line (e.g. https://example.com). Requests from these origins will be served the old vue2-based widget.",
))
])
responses = register_global_settings.send(self)
for r, response in sorted(responses, key=lambda r: str(r[0])):
@@ -12,7 +12,7 @@
<script type="text/javascript" src="{% static "pretixbase/js/gettextstub.js" %}"></script>
<script type="text/javascript" src="{% static "pretixbase/js/details.js" %}"></script>
<script type="text/javascript" src="{% static "pretixcontrol/js/jquery.qrcode.min.js" %}"></script>
<script type="text/javascript" src="{% static "pretixpresale/js/widget/floatformat.js" %}"></script>
<script type="text/javascript" src="{% static "pretixpresale/js/floatformat.js" %}"></script>
<script type="text/javascript" src="{% static "pretixpresale/js/ui/questions.js" %}"></script>
<script type="text/javascript" src="{% static "pretixpresale/js/ui/main.js" %}"></script>
<script type="text/javascript" src="{% static "pretixpresale/js/ui/sso.js" %}"></script>
+17 -52
View File
@@ -122,26 +122,9 @@ def widget_css_etag(request, version, **kwargs):
return f'{_get_source_cache_key(version)}-{request.organizer.cache.get_or_set("css_version", default=lambda: int(time.time()))}'
# use vite by default, serve old vue2-based widget only for widget_vue2_origins
def _use_vite(request):
if getattr(settings, 'PRETIX_WIDGET_VUE', False) or "legacy" in request.GET:
return False
origin = request.META.get('HTTP_ORIGIN', '')
gs = GlobalSettingsObject()
vue_origins = gs.settings.get('widget_vue2_origins', as_type=str, default='')
if vue_origins and not origin:
referer = request.META.get('HTTP_REFERER', '')
origin = '/'.join(referer.split('/', 3)[:3])
if origin and vue_origins:
origins_list = [o.strip() for o in vue_origins.strip().splitlines() if o.strip()]
return origin not in origins_list
return True
def widget_js_etag(request, version, lang, **kwargs):
gs = GlobalSettingsObject()
variant = 'vite' if _use_vite(request) else 'legacy'
return gs.settings.get('widget_checksum_{}_{}_{}'.format(version, lang, variant))
return gs.settings.get('widget_checksum_{}_{}'.format(version, lang))
@gzip_page
@@ -169,16 +152,13 @@ def widget_css(request, version, **kwargs):
return resp
def generate_widget_js(version, lang, use_vite=False):
def generate_widget_js(version, lang):
code = []
with language(lang):
# Provide isolation
code.append('(function (siteglobals) {\n')
code.append('var module = {}, exports = {};\n')
if use_vite:
code.append('const LANG = "%s";\n' % lang)
else:
code.append('var lang = "%s";\n' % lang)
code.append('const LANG = "%s";\n' % lang)
c = JavaScriptCatalog()
c.translation = DjangoTranslation(lang, domain='djangojs')
@@ -202,23 +182,11 @@ def generate_widget_js(version, lang, use_vite=False):
i18n_js = template.render(context)
code.append(i18n_js)
if use_vite:
vite_js = finders.find('vite/widget/widget.js')
if not vite_js:
raise FileNotFoundError('Vite widget build not found. Run: npm run build:widget')
with open(vite_js, 'r', encoding='utf-8') as fp:
code.append(fp.read())
else:
files = [
'vuejs/vue.js' if settings.DEBUG else 'vuejs/vue.min.js',
'pretixpresale/js/widget/docready.js',
'pretixpresale/js/widget/floatformat.js',
'pretixpresale/js/widget/widget.js' if version == version_max else 'pretixpresale/js/widget/widget.v{}.js'.format(version),
]
for fname in files:
f = finders.find(fname)
with open(f, 'r', encoding='utf-8') as fp:
code.append(fp.read())
vite_js = finders.find('vite/widget/widget.js')
if not vite_js:
raise FileNotFoundError('Vite widget build not found. Run: npm run build:widget')
with open(vite_js, 'r', encoding='utf-8') as fp:
code.append(fp.read())
if settings.DEBUG:
code.append('})(this);\n')
@@ -230,14 +198,13 @@ def generate_widget_js(version, lang, use_vite=False):
return f"/* v{version} */\n" + code
def get_widget_js(version, lang, use_vite, force_regenerate=False):
def get_widget_js(version, lang, force_regenerate=False):
if settings.DEBUG:
return generate_widget_js(version, lang, use_vite=use_vite).encode()
return generate_widget_js(version, lang).encode()
variant = 'vite' if use_vite else 'legacy'
cache_prefix = 'widget_js_data_v{}_{}_{}'.format(version, lang, variant)
settings_key = 'widget_file_v{}_{}_{}'.format(version, lang, variant)
checksum_key = 'widget_checksum_v{}_{}_{}'.format(version, lang, variant)
cache_prefix = 'widget_js_data_v{}_{}'.format(version, lang)
settings_key = 'widget_file_v{}_{}'.format(version, lang)
checksum_key = 'widget_checksum_v{}_{}'.format(version, lang)
gs = GlobalSettingsObject()
if not force_regenerate:
@@ -259,7 +226,7 @@ def get_widget_js(version, lang, use_vite, force_regenerate=False):
else:
fname = gs.settings.get(settings_key)
data = generate_widget_js(version, lang, use_vite=use_vite).encode()
data = generate_widget_js(version, lang).encode()
checksum = hashlib.sha1(data).hexdigest()
should_save = (
not fname
@@ -267,7 +234,7 @@ def get_widget_js(version, lang, use_vite, force_regenerate=False):
)
if should_save:
newname = default_storage.save(
'widget/widget.{}.{}.{}.{}.js'.format(version, lang, variant, checksum),
'widget/widget.{}.{}.{}.js'.format(version, lang, checksum),
ContentFile(data)
)
gs.settings.set(settings_key, 'file://' + newname)
@@ -284,8 +251,7 @@ def get_widget_js(version, lang, use_vite, force_regenerate=False):
def regenerate_all_widget_js():
for lc, ll in settings.LANGUAGES:
for version in range(version_min, version_max + 1):
for use_vite in [True, False]:
get_widget_js(version, lc, use_vite, force_regenerate=True)
get_widget_js(version, lc, force_regenerate=True)
@gzip_page
@@ -297,8 +263,7 @@ def widget_js(request, version, lang, **kwargs):
if version < version_min:
version = version_min
use_vite = _use_vite(request)
data = get_widget_js(version, lang, use_vite)
data = get_widget_js(version, lang)
resp = HttpResponse(data, content_type='text/javascript')
resp['Access-Control-Allow-Origin'] = '*'
-1
View File
@@ -913,7 +913,6 @@ VITE_DEV_SERVER_PORT = 5173
VITE_DEV_SERVER = f"http://localhost:{VITE_DEV_SERVER_PORT}"
VITE_DEV_MODE = DEBUG
VITE_IGNORE = False # Used to ignore `collectstatic`/`rebuild`
PRETIX_WIDGET_VUE = os.environ.get('PRETIX_WIDGET_VUE', '') not in ('', '0')
if DEBUG:
# Reload if settings file changes
@@ -1,81 +0,0 @@
// Pure-js replacement for $.ready
// by John Friend, https://github.com/jfriend00/docReady
// MIT License
(function (funcName, baseObj) {
'use strict'
// The public function name defaults to window.docReady
// but you can modify the last line of this function to pass in a different object or method name
// if you want to put them in a different namespace and those will be used instead of
// window.docReady(...)
funcName = funcName || 'docReady'
baseObj = baseObj || window
let readyList = []
let readyFired = false
let readyEventHandlersInstalled = false
// call this when the document is ready
// this function protects itself against being called more than once
function ready () {
if (!readyFired) {
// this must be set to true before we start calling callbacks
readyFired = true
for (let i = 0; i < readyList.length; i++) {
// if a callback here happens to add new ready handlers,
// the docReady() function will see that it already fired
// and will schedule the callback to run right after
// this event loop finishes so all handlers will still execute
// in order and no new ones will be added to the readyList
// while we are processing the list
readyList[i].fn.call(window, readyList[i].ctx)
}
// allow any closures held by these functions to free
readyList = []
}
}
function readyStateChange () {
if (document.readyState === 'complete') {
ready()
}
}
// This is the one public interface
// docReady(fn, context);
// the context argument is optional - if present, it will be passed
// as an argument to the callback
baseObj[funcName] = function (callback, context) {
if (typeof callback !== 'function') {
throw new TypeError('callback for docReady(fn) must be a function')
}
// if ready has already fired, then just schedule the callback
// to fire asynchronously, but right away
if (readyFired) {
setTimeout(function () { callback(context) }, 1)
return
} else {
// add the function and context to the list
readyList.push({ fn: callback, ctx: context })
}
// if document already ready to go, schedule the ready function to run
// IE only safe when readyState is "complete", others safe when readyState is "interactive"
if (document.readyState === 'complete' || (!document.attachEvent && document.readyState === 'interactive')) {
setTimeout(ready, 1)
} else if (!readyEventHandlersInstalled) {
// otherwise if we don't have event handlers installed, install them
if (document.addEventListener) {
// first choice is DOMContentLoaded event
document.addEventListener('DOMContentLoaded', ready, false)
// backup is window load event
window.addEventListener('load', ready, false)
} else {
// must be IE
document.attachEvent('onreadystatechange', readyStateChange)
window.attachEvent('onload', ready)
}
readyEventHandlersInstalled = true
}
}
})('docReady', window)
// modify this previous line to pass in your own method name
// and object for the method to be attached to
File diff suppressed because it is too large Load Diff
-2
View File
@@ -89,8 +89,6 @@ def _widget_assets():
f'Start it with: npm run dev:widget'
)
yield
elif os.environ.get("PRETIX_WIDGET_VUE"):
yield # Old widget, no build needed
else:
subprocess.check_call(['npm', 'run', 'build:widget'], cwd=PROJECT_ROOT)
yield