PageSourceSearch

https://salescare.nl/js/jasper/validation/validation-panel.js?v=b496ea6b

js salescare.nl collected 2026-10-08 12:16:00 UTC 4,963 bytes, 111 lines download raw bytes

1/* ===== Native Jasper Report Editor / Check tab (item cec0e7f4, F3) =====
2 *
3 * validation-panel.js — ported from the legacy editor's
4 * `validation/jasper-validation.component.ts` (234 lines). The "Check" tab:
5 * runs the pure `validateReport` rule set (state/validation.js), groups the
6 * results into errors / warnings, renders each as a clickable row that selects
7 * and scrolls to the offending element, and drives the tab's badge counts.
8 */
9
10(function (global) {
11  'use strict';
12
13  const req = (typeof require === 'function');
14  const NS = (!req && global.JasperEditor) ? global.JasperEditor : null;
15  const validationMod = req ? require('../state/validation.js') : NS.validation;
16  const { validateReport } = validationMod;
17
18  /** Split issues into error / warning groups (errors first). */
19  function groupIssues(issues) {
20    return {
21      errors: (issues || []).filter((i) => i.severity === 'error'),
22      warnings: (issues || []).filter((i) => i.severity === 'warning'),
23    };
24  }
25
26  /** Badge counts for the Check tab: {errors, warnings, total}. */
27  function badgeCounts(issues) {
28    const g = groupIssues(issues);
29    return { errors: g.errors.length, warnings: g.warnings.length, total: (issues || []).length };
30  }
31
32  function esc(s) {
33    return String(s == null ? '' : s).replace(/[&<>"']/g, (c) => (
34      { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
35  }
36
37  /** Render the Check tab (reference: jasper-validation.component — header
38   *  with count pills, issue rows with mono icon / message / detail / where,
39   *  and a Declare-$F quick fix for unknown-field warnings). `onSelect(path)`
40   *  is called with the element path of a clicked issue. */
41  function unknownFieldName(issue) {
42    const m = /^Unknown field \$F\{(\w+)\}/.exec(issue.message || '');
43    return m ? m[1] : null;
44  }
45
46  function render(store, host, onSelect) {
47    const r = store && store.report();
48    if (!host) return;
49    const issues = r ? validateReport(r) : [];
50    const { errors, warnings } = groupIssues(issues);
51    const pills = [];
52    if (errors.length) pills.push(`<span class="vp-pill err">${errors.length} error${errors.length === 1 ? '' : 's'}</span>`);
53    if (warnings.length) pills.push(`<span class="vp-pill warn">${warnings.length} warning${warnings.length === 1 ? '' : 's'}</span>`);
54    if (!issues.length) pills.push('<span class="vp-pill ok">all clear</span>');
55
56    const rowsWithPaths = [];
57    const issueRow = (issue) => {
58      const gi = rowsWithPaths.push(issue) - 1;
59      const fieldName = unknownFieldName(issue);
60      const where = issue.path
61        ? `${issue.path.section || ''}${issue.path.groupName ? ' / ' + issue.path.groupName : ''} · #${(issue.path.indices || []).join('.')}`
62        : '';
63      return `<li class="vp-issue vp-${esc(issue.severity)}" data-g="${gi}">
64        <span class="vp-icon">${issue.severity === 'error' ? '✕' : '!'}</span>
65        <div>
66          <span class="vp-msg">${esc(issue.message)}</span>
67          ${issue.detail ? `<span class="vp-detail">${esc(issue.detail)}</span>` : ''}
68          ${where ? `<span class="vp-where">${esc(where)}</span>` : ''}
69          ${fieldName ? `<button type="button" class="vp-fix" data-field="${esc(fieldName)}" style="display:inline-block;margin-top:4px;padding:2px 8px;font-size:10px;font-family:inherit;background:#e8edff;color:#4a6cf7;border:1px solid #c3cdf9;border-radius:3px;cursor:pointer;line-height:1.4">Declare $F{${esc(fieldName)}}</button>` : ''}
70        </div>
71      </li>`;
72    };
73
74    host.innerHTML = `
75      <div class="vp-header"><span>Validation</span><span class="vp-counts">${pills.join('')}</span></div>` +
76      (issues.length
77        ? `<ul class="vp-list">${issues.map(issueRow).join('')}</ul>`
78        : '<div class="vp-empty">No problems detected.</div>');
79
80    host.querySelectorAll('.vp-issue').forEach((li) => {
81      li.onclick = () => {
82        const issue = rowsWithPaths[Number(li.getAttribute('data-g'))];
83        if (issue && issue.path) {
84          if (onSelect) onSelect(issue.path);
85          else if (store.select) store.select(issue.path);
86        }
87      };
88    });
89    host.querySelectorAll('.vp-fix').forEach((btn) => {
90      btn.onclick = (e) => {
91        e.stopPropagation();
92        const name = btn.getAttribute('data-field');
93        const rep = store.report();
94        if (!rep || (rep.fields || []).some((f) => f.name === name)) return;
95        store.updateReport((cur) => Object.assign({}, cur, {
96          fields: [...(cur.fields || []), { name, class: 'java.lang.String' }],
97        }));
98        render(store, host, onSelect);
99      };
100    });
101  }
102
103  const api = { validateReport, groupIssues, badgeCounts, render };
104
105  if (typeof module !== 'undefined' && module.exports) {
106    module.exports = api;
107  } else {
108    const NSg = (global.JasperEditor = global.JasperEditor || {});
109    NSg.validationPanel = api;
110  }
111})(typeof self !== 'undefined' ? self : this);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.