{% if render_mode != 'fragment' %} {% if domain %}{% endif %} Component List - Finite State Report {# ECharts library — replaces Chart.js v4.4.1 + chartjs-plugin-datalabels from the pre-migration template. ECharts has native series.label.formatter for the count + percentage labels the datalabels plugin used to provide. #} {% include "_design_system.html" %} {% include "_console_shell.html" %} {% include "_echarts_ready.html" %} {% endif %} {# Recipe-local styles — render in BOTH standalone and fragment modes so fragment_extractor (_STYLE_RE) collects them, scopes under .fs-section-component-list, and re-emits at the top of the fragment. #} {% if render_mode != 'fragment' %} {% endif %} {% import "_console_macros.html" as fs with context %} {# Defensive defaults — mirrors B.1 cve_component_evidence + license_report. `component_summary` is reachable via two paths: - top-level `component_summary` (promoted by report_engine.py:5619-5620) - nested transform_result.component_summary (preserved by the data_transformer dict-storage path) Round-1 multi-review M1-9: fall back to the top-level key when the nested path is missing so paths that populate only one side still render KPIs + charts. #} {% set transform_result = transform_result | default({}) %} {% if not transform_result is mapping %}{% set transform_result = {} %}{% endif %} {% set summary = transform_result.get('component_summary') %} {% if not summary %}{% set summary = component_summary | default({}) %}{% endif %} {% if not summary is mapping %}{% set summary = {} %}{% endif %} {% set data = data | default([]) %} {# Build topbar meta items preserving the pre-migration context that the legacy template surfaced in its .metadata block (period, folder, project) — round-1 multi-review M1-4 / M1-15. #} {% set cl_meta = [{"label": "Domain", "value": domain or "—"}] %} {% if metadata and metadata.get('start_date') and metadata.get('end_date') %} {% set _ = cl_meta.append({"label": "Period", "value": (metadata.start_date | string) ~ " → " ~ (metadata.end_date | string)}) %} {% endif %} {% if folder_path %} {% set _ = cl_meta.append({"label": "Folder", "value": folder_path}) %} {% endif %} {% if project_label %} {% set _ = cl_meta.append({"label": "Project", "value": project_label}) %} {% endif %} {% set _ = cl_meta.append({"label": "Components", "value": (summary.get('total_components', data | length)) | string}) %} {% set _ = cl_meta.append({"label": "Generated", "value": generated_at or "—"}) %} {% if render_mode != 'fragment' %} {{ fs.topbar( crumbs=["Finite State", "Component List"], meta=cl_meta, controls=[], ) }} {% endif %}

Component List

Software Component Inventory & License Analysis

{# Applied Filter panel — preserved from pre-migration template (component_list.html:44-51). Surfaces folder + project scope when either is set. Round-1 multi-review M1-4. #} {% if folder_path or project_label %}
{{ fs.panel_head("Applied filter", meta="scope") }}
{% if folder_path %}

Folder: {{ folder_path }}

{% endif %} {% if project_label %}

Project filter: {{ project_label }}

{% endif %}

Showing components for the specified scope only.

{% endif %} {% if summary %} {# 5 KPI cells. #}
{{ fs.kpi_cell("Total Components", summary.get('total_components', 0)) }} {{ fs.kpi_cell("Unique Licenses", summary.get('unique_licenses', 0)) }} {{ fs.kpi_cell( "No License", summary.get('no_license_count', 0), dot=("high" if (summary.get('no_license_count', 0)) > 0 else None), ) }} {{ fs.kpi_cell( "Policy Violations", summary.get('violation_count', 0), dot=("critical" if (summary.get('violation_count', 0)) > 0 else None), ) }} {% set cl_total = (summary.get('copyleft_strong', 0) | int) + (summary.get('copyleft_weak', 0) | int) %} {{ fs.kpi_cell( "Copyleft Components", cl_total, dot=("high" if cl_total > 0 else None), ) }}
{# Charts row 1: License Distribution + Policy Status. #}
{{ fs.panel_head("License distribution", meta="top licenses by count") }} {% if render_mode == 'fragment' and not fragment_scripts_enabled %}
Chart unavailable in fragment view
{% else %}
{% endif %}
{{ fs.panel_head("Policy status", meta="license policy compliance") }} {% if render_mode == 'fragment' and not fragment_scripts_enabled %}
Chart unavailable in fragment view
{% else %}
{% endif %}
{# Charts row 2: Copyleft + Source. #}
{{ fs.panel_head("Copyleft classification", meta="copyleft obligation breakdown") }} {% if render_mode == 'fragment' and not fragment_scripts_enabled %}
Chart unavailable in fragment view
{% else %}
{% endif %}
{{ fs.panel_head("Source type", meta="how components were discovered") }} {% if render_mode == 'fragment' and not fragment_scripts_enabled %}
Chart unavailable in fragment view
{% else %}
{% endif %}
{% endif %} {# Component inventory table. #}
{{ fs.panel_head("Component inventory", meta=((data | length) | string) ~ " component" ~ ("s" if (data | length) != 1 else "")) }}

Comprehensive software component inventory with license details.

{% if data and (data | length) > 0 %} {% if folder_path %}{% endif %} {% set current_project = namespace(value=None) %} {% for row in data[:2000] %} {% if row['Project Name'] != current_project.value %} {% set current_project.value = row['Project Name'] %} {% endif %} {% set ttype_slug = (row.get('Type', '') | string | lower | replace(' ', '-')) or 'default' %} {% set cs = row.get('Copyleft Status', '') %} {% set pol = (row.get('Policy Status', '') | string | lower) %} {% set cstatus = row.get('Component Status', '') %} {% set findings = row.get('Findings', 0) | int %} {% if folder_path %}{% endif %} {% endfor %}
Group Component Version Type Source Declared License Concluded License Copyleft PolicyFolderProject Project Version BOM Reference Findings Status License URL Release Date
{{ row['Project Name'] }}
{{ row.get('Group', '') }} {{ row['Component'] }} {{ row['Version'] }} {{ row.get('Type', '') }} {{ row.get('Source', '') }} {{ row.get('Declared License', '') }} {% if row.get('Concluded License') %} {{ row['Concluded License'] }} {% endif %} {% if cs == 'STRONG_COPYLEFT' %}Strong {% elif cs == 'WEAK_COPYLEFT' %}Weak {% elif cs == 'PERMISSIVE' %}Permissive {% else %}-{% endif %} {% if pol %}{{ row.get('Policy Status', '') }} {% else %}-{% endif %} {{ row.get('Folder', '') }}{{ row['Project Name'] }} {{ row['Project Version'] }} {{ row.get('BOM Reference', '') }} {% if findings >= 10 %}{{ findings }} {% elif findings >= 5 %}{{ findings }} {% elif findings > 0 %}{{ findings }} {% else %}0{% endif %} {% if cstatus and cstatus != 'N/A' %} {{ cstatus }} {% else %}-{% endif %} {% set lurl = row.get('License URL', '') %} {% if lurl %}Link {% else %}-{% endif %} {% set rd = row.get('Release Date', '') %} {% if rd %}{{ rd }}{% else %}-{% endif %}
{% if (data | length) > 2000 %}

Showing 2,000 of {{ data | length }} rows. See CSV/XLSX export for full data.

{% endif %} {% else %}

No components found

No software components match the current criteria.

{% endif %}
{% if render_mode != 'fragment' %} {{ fs.status_bar(items=[ "Recipe: Component List", "Components: " ~ ((summary.get('total_components', data | length)) | string), generated_at | default(''), ], version='fs-report ' ~ (fs_report_version | default('dev'))) }} {% endif %} {% if render_mode != 'fragment' or fragment_scripts_enabled %} {% include '_action_buttons.html' %} {% endif %}