Files
breadcrumb-the-shire/web/js/pages/app-list-utils.js
fs 25370a1a55 add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00

66 lines
1.9 KiB
JavaScript

export const buildUrl = (appBase, path) => new URL(path, appBase).toString();
export const getAppBase = () => {
const baseEl = document.querySelector('base');
if (baseEl && baseEl.href) {
return baseEl.href;
}
return `${window.location.origin}/`;
};
export const escapeHtml = (value) => String(value ?? '').replace(/[&<>"']/g, (char) => ({
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;'
}[char]));
export const buildBadgeList = (items, options = {}) => {
const {
variant = 'neutral',
primaryVariant = 'info',
primaryTooltip = ''
} = options;
let list = items;
let primary = '';
if (items && typeof items === 'object' && !Array.isArray(items)) {
list = Array.isArray(items.items) ? items.items : [];
primary = String(items.primary ?? '');
}
if (!Array.isArray(list) || list.length === 0) {return '';}
const tooltipAttr = primaryTooltip
? ` data-tooltip="${escapeHtml(primaryTooltip)}" data-tooltip-pos="top"`
: '';
const badges = list.map((label) => {
const labelText = String(label ?? '');
const isPrimary = primary !== '' && labelText === primary;
const badgeVariant = isPrimary ? primaryVariant : variant;
const badgeTooltip = isPrimary && primaryTooltip ? tooltipAttr : '';
return `<span class="badge" data-variant="${badgeVariant}"${badgeTooltip}>${escapeHtml(labelText)}</span>`;
}).join(' ');
return `<div class="badge-list">${badges}</div>`;
};
export const postAction = async (url, csrf, data = {}) => {
const body = new URLSearchParams({ ...data, [csrf.key]: csrf.token });
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'X-Requested-With': 'fetch'
},
body
});
};
export const badgeHtml = (gridjs, value = '') => {
const safe = value ?? '';
return gridjs.html(`<span class="badge" data-variant="neutral">${safe}</span>`);
};