From 583d464d6f4f7e6baa9c6ed6c75458205ae00997 Mon Sep 17 00:00:00 2001 From: Mira Weller Date: Wed, 16 Sep 2026 15:08:42 +0200 Subject: [PATCH] progress bar --- .../js/ui/questionnaires/ProgressBar.ts | 71 +++++++++++++++++++ .../pretixcontrol/js/ui/questionnaires/api.ts | 35 +++++---- 2 files changed, 91 insertions(+), 15 deletions(-) create mode 100644 src/pretix/static/pretixcontrol/js/ui/questionnaires/ProgressBar.ts diff --git a/src/pretix/static/pretixcontrol/js/ui/questionnaires/ProgressBar.ts b/src/pretix/static/pretixcontrol/js/ui/questionnaires/ProgressBar.ts new file mode 100644 index 0000000000..14930e0075 --- /dev/null +++ b/src/pretix/static/pretixcontrol/js/ui/questionnaires/ProgressBar.ts @@ -0,0 +1,71 @@ + +type MyAttrs = { + [key: `on${any}`]: EventListener, style?: {[key:string]: string} | string, innerHTML?: string, + appendTo?: HTMLElement | ShadowRoot, prependTo?: HTMLElement | ShadowRoot, insertBefore?: HTMLElement, insertAfter?: HTMLElement, + [key: Exclude]: any, +}; + +export function EL(tagName: K, attrs:MyAttrs, ...children:(string|HTMLElement)[]): HTMLElementTagNameMap[K]; +export function EL(tagName:string, attrs:MyAttrs, ...children:(string|HTMLElement)[]) : HTMLElement; +export function EL(tagName:string, attrs:MyAttrs, ...children:(string|HTMLElement)[]) : HTMLElement { + if (attrs?.idGetOrCreate) { + const el = document.getElementById(attrs.idGetOrCreate); + if (el) { + return el; + } else { + attrs.id = attrs.idGetOrCreate; delete attrs.idGetOrCreate; + } + } + var el = document.createElement(tagName); + if (attrs) for(var key in attrs) + if (key === 'style' && typeof attrs[key] === 'object') Object.assign(el.style, attrs[key]); + else if (key === 'component' && 'args' in attrs) el['Component'] = new attrs.component(el, ...attrs.args); + else if (key === 'innerHTML') el.innerHTML = attrs[key]; + else if (key === 'appendTo' && (attrs.appendTo instanceof HTMLElement || attrs.appendTo instanceof ShadowRoot)) attrs.appendTo.append(el); + else if (key === 'prependTo' && (attrs.prependTo instanceof HTMLElement || attrs.prependTo instanceof ShadowRoot)) attrs.prependTo.prepend(el); + else if (key === 'insertBefore' && attrs.insertBefore instanceof HTMLElement) attrs.insertBefore.before(el); + else if (key === 'insertAfter' && attrs.insertAfter instanceof HTMLElement) attrs.insertAfter.after(el); + else if (key.startsWith("on")) el.addEventListener(key.substring(2), attrs[key] as unknown as EventListener, false); + else if (key.startsWith(":")) el[key.substring(1)] = attrs[key]; + else if (key === 'checked' && 'checked' in el) el.checked = attrs.checked; + else if (key === 'disabled' && 'disabled' in el) el.disabled = attrs.disabled; + else if (key === 'selected' && 'selected' in el) el.selected = attrs.selected; + else if (key === 'multiple' && 'multiple' in el) el.multiple = attrs.multiple; + else el.setAttribute(key, attrs[key]); + + for(var i=0;ichildren[i]); + else if (children[i]) el.appendChild(document.createTextNode(""+children[i])); + } + return el; +} + +export class ProgressBar { + private static container : HTMLDivElement = EL('div', { appendTo: document.body, class: 'progressBar' }, EL('div', {class:'progressBarText'})); + + static show(message?: string, max?: number) { + const texts = ProgressBar.container.lastElementChild; + const bar = EL('div', {class:'progressBar_progress'+(max ? '' : ' indeterminate')}); + let text : HTMLElement; + if (message) { + text = EL('span', {}, message); + texts.append(text); + } + texts.before(bar); + return { + disposed: false, + [Symbol.dispose]() { + if (this.disposed) return; + bar.remove(); + if (text) text.remove(); + this.disposed = true; + }, + set message(val: string) { + text.innerText = val; + }, + set progress(val: number) { + if (max) bar.style.width = `${val / max * 100}%`; + } + }; + } +} diff --git a/src/pretix/static/pretixcontrol/js/ui/questionnaires/api.ts b/src/pretix/static/pretixcontrol/js/ui/questionnaires/api.ts index 82f2ae7751..5250928b70 100644 --- a/src/pretix/static/pretixcontrol/js/ui/questionnaires/api.ts +++ b/src/pretix/static/pretixcontrol/js/ui/questionnaires/api.ts @@ -1,22 +1,23 @@ -import {ApiListResponse, Datafield, Questionnaire, Item} from "./model"; +import { ApiListResponse, Datafield, Questionnaire, Item, Category } from './model' +import { ProgressBar } from "./ProgressBar"; const organizer_slug = document.body.getAttribute('data-organizer'), - event_slug = document.body.getAttribute('data-event'); + event_slug = document.body.getAttribute('data-event') async function api_get(resource) { - return await $.getJSON(`/api/v1/${resource}?_nocache=${+new Date()}`); + return await $.getJSON(`/api/v1/${resource}?_nocache=${+new Date()}`) } async function api_get_all(resource): Promise { - let next = `/api/v1/${resource}?_nocache=${+new Date()}`; + let next = `/api/v1/${resource}?_nocache=${+new Date()}` const result: T[] = []; while (next) { - const response: ApiListResponse = await $.getJSON(next); - result.push(...response.results); - next = response.next; - console.log('api_get_all: '+ resource, next, response, result) + const response: ApiListResponse = await $.getJSON(next) + result.push(...response.results) + next = response.next + console.log('api_get_all: ' + resource, next, response, result) } - return result; + return result } async function api_json_request(resource, method, json_body) { @@ -24,17 +25,19 @@ async function api_json_request(resource, method, json_body) { body: JSON.stringify(json_body), method: method, headers: { - "Content-Type": "application/json", - "X-CSRFToken": $('[name=csrfmiddlewaretoken]').val() as string, + 'Content-Type': 'application/json', + 'X-CSRFToken': $('[name=csrfmiddlewaretoken]').val() as string, }, - })).json(); + })).json() } -export async function getDatafields() { - return await api_get_all(`organizers/${organizer_slug}/events/${event_slug}/datafields/`); +export async function getDatafields(container_type) { + using pb = ProgressBar.show('loading data fields') + return await api_get_all(`organizers/${organizer_slug}/events/${event_slug}/datafields/?container_type=${container_type}&`); } export async function getQuestionnaires() { + using pb = ProgressBar.show('loading questionnaires') return await api_get_all(`organizers/${organizer_slug}/events/${event_slug}/questionnaires/`); } @@ -47,11 +50,13 @@ export async function createQuestionnaire(data) { } export async function getItems() { + using pb = ProgressBar.show('loading product list') return await api_get_all(`organizers/${organizer_slug}/events/${event_slug}/items/`); } export async function getCategories() { - return await api_get_all(`organizers/${organizer_slug}/events/${event_slug}/categories/`); + using pb = ProgressBar.show('loading category list') + return await api_get_all(`organizers/${organizer_slug}/events/${event_slug}/categories/`); } function get_json_script_value(id) {