software package profiles implemeted, job deletion optimized
This commit is contained in:
@@ -136,5 +136,5 @@
|
||||
document.documentElement.classList.toggle('sidebar-collapsed-preset', collapsed);
|
||||
});
|
||||
})();
|
||||
</script><script src="/static/js/asset-page-boot.js"></script><script src="/static/js/presence.js"></script><script src="/static/js/software-inventory-selection.js?v={{ app_version }}"></script>
|
||||
</script><script src="/static/js/asset-page-boot.js"></script><script src="/static/js/presence.js"></script><script src="/static/js/file-picker.js?v={{ app_version }}"></script><script src="/static/js/software-inventory-selection.js?v={{ app_version }}"></script>
|
||||
</body></html>
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
<h2>{{ t('settings.system_information') }}</h2>
|
||||
<p class="muted">{{ t('settings.system_information_file_help') }}</p>
|
||||
<dl class="system-info-grid">
|
||||
<dt>{{ t('settings.appinfo_path') }}</dt><dd><code>/app/config/APPINFO.json</code></dd>
|
||||
<dt>{{ t('settings.appinfo_path') }}</dt><dd><code>{{ application_info_path() }}</code></dd>
|
||||
<dt>{{ t('about.version') }}</dt><dd>{{ application_version() }}</dd>
|
||||
<dt>{{ t('about.author') }}</dt><dd>{{ appinfo.author or '—' }}</dd>
|
||||
<dt>{{ t('about.organization') }}</dt><dd>{{ appinfo.organization or '—' }}</dd>
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
<section class="panel">
|
||||
<h2>{{ t('settings.backup_planned', 'Datenbanksicherung ist für v0.3.15.0 vorgesehen') }}</h2>
|
||||
<p>{{ t('settings.backup_planned_help', 'Die automatische Sicherung alle 8 Stunden, eine Aufbewahrung von 3 Tagen sowie Download, Upload, manuelles Backup und Wiederherstellung werden im nächsten Entwicklungsschritt umgesetzt.') }}</p>
|
||||
<p><strong>{{ t('settings.backup_directory', 'Backup-Verzeichnis') }}:</strong> <code>/app/data/backups</code></p>
|
||||
<p><strong>{{ t('settings.backup_directory', 'Backup-Verzeichnis') }}:</strong> <code>/assetmanager-data/backups</code></p>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
@@ -76,6 +76,39 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel software-settings-section">
|
||||
<div class="software-settings-section-heading">
|
||||
<div>
|
||||
<h2>{{ t('software.settings.remote_cleanup_title') }}</h2>
|
||||
<p class="muted">{{ t('software.settings.remote_cleanup_help') }}</p>
|
||||
</div>
|
||||
<span class="software-settings-badge">{{ t('software.settings.remote_cleanup_badge') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="software-settings-grid">
|
||||
<label class="software-toggle-option software-settings-wide">
|
||||
<input type="checkbox" name="remote_job_cleanup_enabled" {% if software_settings.get('remote_job_cleanup_enabled', true) %}checked{% endif %}>
|
||||
<span class="software-toggle-track"><span class="software-toggle-thumb"></span></span>
|
||||
<span>
|
||||
<strong>{{ t('software.settings.remote_cleanup_enabled') }}</strong>
|
||||
<small>{{ t('software.settings.remote_cleanup_enabled_help') }}</small>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
{{ t('software.settings.remote_cleanup_hours') }}
|
||||
<input type="number" name="remote_job_retention_hours" min="1" max="8760" step="1" value="{{ software_settings.get('remote_job_retention_hours', 24) }}">
|
||||
<small>{{ t('software.settings.remote_cleanup_hours_help') }}</small>
|
||||
</label>
|
||||
|
||||
<div class="software-callback-preview">
|
||||
<span>{{ t('software.settings.remote_cleanup_paths') }}</span>
|
||||
<code>C:\ProgramData\AssetManager\Jobs</code>
|
||||
<code>/var/lib/assetmanager/jobs</code>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel software-settings-section">
|
||||
<div class="software-settings-section-heading">
|
||||
<div>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<p class="muted">{{ t('setup_analyzer.subtitle') }}</p>
|
||||
</div>
|
||||
<div class="setup-analyzer-actions">
|
||||
<a class="button button-secondary" href="/software/setup-analyzer/profiles">{{ t('setup_profiles.manage') }}</a>
|
||||
<a class="button button-secondary" href="/software/packages">{{ t('software_packages.title') }}</a>
|
||||
<a class="button button-secondary" href="/software">{{ t('setup_analyzer.back_to_software') }}</a>
|
||||
</div>
|
||||
@@ -15,9 +16,12 @@
|
||||
<h2>{{ t('setup_analyzer.upload_title') }}</h2>
|
||||
<p>{{ t('setup_analyzer.static_note') }}</p>
|
||||
<form class="setup-analyzer-form" method="post" action="/software/setup-analyzer/analyze" enctype="multipart/form-data">
|
||||
<label for="installer">{{ t('setup_analyzer.file') }}
|
||||
<input id="installer" name="installer" type="file" accept=".exe,.msi,.msp,.msix,.appx,.msu" required>
|
||||
</label>
|
||||
<label for="installer">{{ t('setup_analyzer.file') }}</label>
|
||||
<div class="localized-file-picker" data-file-picker>
|
||||
<input class="localized-file-picker-input" id="installer" name="installer" type="file" accept=".exe,.msi,.msp,.msix,.appx,.msu" required data-file-picker-input>
|
||||
<button class="button button-secondary localized-file-picker-button" type="button" data-file-picker-button aria-controls="installer">{{ t('common.choose_file') }}</button>
|
||||
<span class="localized-file-picker-name" data-file-picker-name data-empty-text="{{ t('common.no_file_selected') }}" aria-live="polite">{{ t('common.no_file_selected') }}</span>
|
||||
</div>
|
||||
<p class="muted">{{ t('setup_analyzer.max_upload', size=max_upload_mb) }}</p>
|
||||
<button class="button" type="submit">{{ t('setup_analyzer.analyze') }}</button>
|
||||
</form>
|
||||
@@ -63,6 +67,45 @@
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{% if analysis.sfx_analysis %}
|
||||
<section class="panel setup-analyzer-card">
|
||||
<h2>{{ t('setup_analyzer.sfx_title') }}</h2>
|
||||
<dl class="setup-analyzer-details">
|
||||
<dt>{{ t('setup_analyzer.sfx_container') }}</dt><dd>{{ analysis.sfx_analysis.container_label }}</dd>
|
||||
<dt>{{ t('setup_analyzer.sfx_status') }}</dt><dd>{{ t('setup_analyzer.sfx_status.' ~ analysis.sfx_analysis.status) }}</dd>
|
||||
<dt>{{ t('setup_analyzer.sfx_extractor') }}</dt><dd>{{ analysis.sfx_analysis.extractor or t('setup_analyzer.not_available') }}</dd>
|
||||
<dt>{{ t('setup_analyzer.sfx_files') }}</dt><dd>{{ analysis.sfx_analysis.file_count }}</dd>
|
||||
<dt>{{ t('setup_analyzer.sfx_size') }}</dt><dd>{{ analysis.sfx_analysis.extracted_size_human }}</dd>
|
||||
{% if analysis.sfx_analysis.selected %}
|
||||
<dt>{{ t('setup_analyzer.sfx_selected') }}</dt><dd><code>{{ analysis.sfx_analysis.selected.relative_path }}</code></dd>
|
||||
<dt>{{ t('setup_analyzer.technology') }}</dt><dd>{{ analysis.sfx_analysis.selected.installer_label }} ({{ analysis.sfx_analysis.selected.confidence }} %)</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
{% if analysis.sfx_analysis.candidates %}
|
||||
<details>
|
||||
<summary>{{ t('setup_analyzer.sfx_candidates') }} ({{ analysis.sfx_analysis.candidates|length }})</summary>
|
||||
<div class="table-scroll standard-data-table-scroll">
|
||||
<table class="data-table">
|
||||
<thead><tr><th>{{ t('setup_analyzer.file') }}</th><th>{{ t('setup_analyzer.technology') }}</th><th>{{ t('setup_analyzer.confidence') }}</th><th>{{ t('setup_analyzer.product_name') }}</th><th>{{ t('setup_analyzer.version') }}</th></tr></thead>
|
||||
<tbody>
|
||||
{% for candidate in analysis.sfx_analysis.candidates %}
|
||||
<tr{% if analysis.sfx_analysis.selected and candidate.relative_path == analysis.sfx_analysis.selected.relative_path %} class="is-selected"{% endif %}>
|
||||
<td><code>{{ candidate.relative_path }}</code></td>
|
||||
<td>{{ candidate.installer_label }}</td>
|
||||
<td>{{ candidate.confidence }} %</td>
|
||||
<td>{{ candidate.product_name }}</td>
|
||||
<td>{{ candidate.product_version }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% if analysis.sfx_analysis.error %}<p class="muted">{{ analysis.sfx_analysis.error }}</p>{% endif %}
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
{% if analysis.warning_keys %}
|
||||
<section class="panel">
|
||||
<h2>{{ t('setup_analyzer.notes') }}</h2>
|
||||
@@ -97,6 +140,7 @@
|
||||
<input id="install_arguments" name="install_arguments" value="{{ analysis.install_arguments }}">
|
||||
</label>
|
||||
<p><strong>{{ t('setup_analyzer.recommended_command') }}:</strong><br><code>{{ analysis.install_command }}</code></p>
|
||||
{% if analysis.alternative_install_command %}<p><strong>{{ t('setup_analyzer.alternative_command') }}:</strong><br><code>{{ analysis.alternative_install_command }}</code></p>{% endif %}
|
||||
<label for="timeout_seconds">{{ t('setup_analyzer.timeout') }}
|
||||
<input id="timeout_seconds" name="timeout_seconds" type="number" min="30" max="86400" value="600">
|
||||
</label>
|
||||
@@ -116,7 +160,7 @@
|
||||
<small class="muted">{{ t('setup_analyzer.suppress_browser_help') }}</small>
|
||||
</div>
|
||||
<label for="process_names">{{ t('setup_analyzer.process_names') }}
|
||||
<input id="process_names" name="process_names" value="{{ analysis.process_names_default }}" placeholder="Greenshot.exe">
|
||||
<input id="process_names" name="process_names" value="{{ analysis.process_names_default }}" placeholder="ExampleApp.exe">
|
||||
</label>
|
||||
<small class="muted">{{ t('setup_analyzer.process_names_help') }}</small>
|
||||
<div class="setup-analyzer-checkboxes">
|
||||
@@ -164,6 +208,15 @@
|
||||
<dl class="setup-analyzer-details">
|
||||
<dt>{{ t('setup_analyzer.pefile') }}</dt><dd>{{ t('common.yes') if analysis.pefile_available else t('common.no') }}</dd>
|
||||
<dt>msiinfo</dt><dd>{{ t('common.yes') if analysis.msiinfo_available else t('common.no') }}</dd>
|
||||
<dt>7-Zip</dt><dd>{{ t('common.yes') if analysis.archive_tools.sevenzip_available else t('common.no') }}</dd>
|
||||
<dt>unar / lsar</dt><dd>{{ t('common.yes') if analysis.archive_tools.unar_available else t('common.no') }}</dd>
|
||||
<dt>{{ t('setup_analyzer.sfx_limits') }}</dt><dd>{{ max_extracted_mb }} MB / {{ max_extracted_files }} {{ t('setup_analyzer.sfx_files') }} / {{ t('setup_analyzer.sfx_depth', depth=max_sfx_depth) }}</dd>
|
||||
{% if analysis.launcher_architecture %}<dt>{{ t('setup_analyzer.launcher_architecture') }}</dt><dd>{{ analysis.launcher_architecture }}</dd>{% endif %}
|
||||
{% if analysis.architecture_source %}<dt>{{ t('setup_analyzer.architecture_source') }}</dt><dd>{{ t('setup_analyzer.architecture_source.' ~ analysis.architecture_source) }}</dd>{% endif %}
|
||||
{% if analysis.product_version_source %}<dt>{{ t('setup_analyzer.version_source') }}</dt><dd>{{ t('setup_analyzer.metadata_source.' ~ analysis.product_version_source) }}</dd>{% endif %}
|
||||
{% if analysis.manufacturer_source %}<dt>{{ t('setup_analyzer.manufacturer_source') }}</dt><dd>{{ t('setup_analyzer.metadata_source.' ~ analysis.manufacturer_source) }}</dd>{% endif %}
|
||||
{% if analysis.profile_name %}<dt>{{ t('setup_profiles.matched_profile') }}</dt><dd>{{ analysis.profile_name }} {{ analysis.profile_version or '' }} <code>{{ analysis.profile_id }}</code></dd>{% endif %}
|
||||
{% if analysis.profile_source %}<dt>{{ t('setup_profiles.profile_source') }}</dt><dd>{{ t('setup_profiles.source.' ~ analysis.profile_source) }}</dd>{% endif %}
|
||||
{% if analysis.original_filename %}<dt>OriginalFilename</dt><dd>{{ analysis.original_filename }}</dd>{% endif %}
|
||||
</dl>
|
||||
</details>
|
||||
|
||||
Executable
+111
@@ -0,0 +1,111 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="toolbar">
|
||||
<div>
|
||||
<h1>{{ t('setup_profiles.title') }}</h1>
|
||||
<p class="muted">{{ t('setup_profiles.subtitle') }}</p>
|
||||
</div>
|
||||
<div class="setup-analyzer-actions">
|
||||
<a class="button button-secondary" href="/software/setup-analyzer">{{ t('setup_profiles.back') }}</a>
|
||||
<a class="button button-secondary" href="/software/packages">{{ t('software_packages.title') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="panel">
|
||||
<h2>{{ t('setup_profiles.import_title') }}</h2>
|
||||
<p class="muted">{{ t('setup_profiles.import_help') }}</p>
|
||||
<form method="post" action="/software/setup-analyzer/profiles/import" enctype="multipart/form-data" class="setup-analyzer-form">
|
||||
<label for="analyzer-profile-import-file">{{ t('setup_profiles.file') }}</label>
|
||||
<div class="localized-file-picker" data-file-picker>
|
||||
<input class="localized-file-picker-input" id="analyzer-profile-import-file" type="file" name="profile_file" accept=".amprofile,.zip" required data-file-picker-input>
|
||||
<button class="button button-secondary localized-file-picker-button" type="button" data-file-picker-button aria-controls="analyzer-profile-import-file">{{ t('common.choose_file') }}</button>
|
||||
<span class="localized-file-picker-name" data-file-picker-name data-empty-text="{{ t('common.no_file_selected') }}" aria-live="polite">{{ t('common.no_file_selected') }}</span>
|
||||
</div>
|
||||
<label>{{ t('setup_profiles.source') }}
|
||||
<select name="source">
|
||||
<option value="community">{{ t('setup_profiles.source.community') }}</option>
|
||||
<option value="local">{{ t('setup_profiles.source.local') }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<button class="button" type="submit">{{ t('setup_profiles.import_button') }}</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<h2>{{ t('setup_profiles.installed_title') }}</h2>
|
||||
<div class="table-scroll management-table-scroll">
|
||||
<table class="data-table" data-storage-key="setup-analyzer-profiles">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ t('setup_profiles.name') }}</th>
|
||||
<th>{{ t('setup_profiles.id') }}</th>
|
||||
<th>{{ t('setup_analyzer.version') }}</th>
|
||||
<th>{{ t('setup_profiles.kind') }}</th>
|
||||
<th>{{ t('setup_profiles.stage') }}</th>
|
||||
<th>{{ t('setup_profiles.source') }}</th>
|
||||
<th>{{ t('software_packages.status') }}</th>
|
||||
<th>{{ t('jobs.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for profile in profiles %}
|
||||
<tr>
|
||||
<td><strong>{{ profile.name }}</strong></td>
|
||||
<td><code>{{ profile.id }}</code></td>
|
||||
<td>{{ profile.version }}</td>
|
||||
<td>{{ profile.kind }}</td>
|
||||
<td>{{ profile.stage }}</td>
|
||||
<td>{{ t('setup_profiles.source.' ~ profile.source) }}</td>
|
||||
<td>{% if profile.enabled %}<span class="job-status job-status-success">{{ t('software_packages.enabled') }}</span>{% else %}<span class="job-status">{{ t('software_packages.disabled') }}</span>{% endif %}</td>
|
||||
<td>
|
||||
<div class="software-package-row-actions">
|
||||
<a class="button button-secondary button-small" href="/software/setup-analyzer/profiles/{{ profile.id }}/export">{{ t('setup_profiles.export_button') }}</a>
|
||||
<form class="inline-form" method="post" action="/software/setup-analyzer/profiles/{{ profile.id }}/toggle">
|
||||
<input type="hidden" name="enabled" value="{{ '0' if profile.enabled else '1' }}">
|
||||
<button class="button button-secondary button-small" type="submit">{{ t('setup_profiles.disable') if profile.enabled else t('setup_profiles.enable') }}</button>
|
||||
</form>
|
||||
{% if profile.source != 'system' %}
|
||||
<form class="inline-form" method="post" action="/software/setup-analyzer/profiles/{{ profile.id }}/delete" onsubmit="return confirm({{ t('setup_profiles.delete_confirm', profile=profile.name)|tojson }});">
|
||||
<button class="button button-danger button-small" type="submit">{{ t('software_packages.delete_button_short') }}</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="8">{{ t('setup_profiles.none') }}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<h2>{{ t('setup_profiles.repository_title') }}</h2>
|
||||
{% if repository.url %}
|
||||
<p class="muted">{{ t('setup_profiles.repository_url') }} <code>{{ repository.url }}</code></p>
|
||||
{% if not request.query_params.get('repository') %}
|
||||
<a class="button button-secondary" href="/software/setup-analyzer/profiles?repository=1">{{ t('setup_profiles.repository_load') }}</a>
|
||||
{% elif repository_error %}
|
||||
<div class="notice error">{{ repository_error }}</div>
|
||||
{% else %}
|
||||
<div class="table-scroll management-table-scroll">
|
||||
<table class="data-table" data-storage-key="setup-analyzer-repository">
|
||||
<thead><tr><th>{{ t('setup_profiles.name') }}</th><th>{{ t('setup_analyzer.version') }}</th><th>{{ t('setup_profiles.id') }}</th><th>{{ t('jobs.actions') }}</th></tr></thead>
|
||||
<tbody>
|
||||
{% for item in repository.profiles %}
|
||||
<tr>
|
||||
<td>{{ item.name or item.id }}</td><td>{{ item.version or '—' }}</td><td><code>{{ item.id }}</code></td>
|
||||
<td><form method="post" action="/software/setup-analyzer/profiles/repository/install"><input type="hidden" name="profile_id" value="{{ item.id }}"><button class="button button-small" type="submit">{{ t('setup_profiles.repository_install') }}</button></form></td>
|
||||
</tr>
|
||||
{% else %}<tr><td colspan="4">{{ t('setup_profiles.repository_empty') }}</td></tr>{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p class="muted">{{ t('setup_profiles.repository_not_configured') }}</p>
|
||||
<p><code>ANALYZER_PROFILE_REPOSITORY_URL=https://.../index.json</code></p>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -6,6 +6,7 @@
|
||||
<p class="muted">{{ t('software_packages.detail_subtitle') }}</p>
|
||||
</div>
|
||||
<div class="setup-analyzer-actions">
|
||||
<a class="button button-secondary" href="/software/packages/{{ package.id }}/export">{{ t('software_packages.export_button') }}</a>
|
||||
<a class="button button-secondary" href="/software/packages">{{ t('software_packages.back') }}</a>
|
||||
<a class="button button-secondary" href="/software">{{ t('setup_analyzer.back_to_software') }}</a>
|
||||
</div>
|
||||
@@ -51,7 +52,7 @@
|
||||
<p class="muted">{{ t('software_packages.process_control_help') }}</p>
|
||||
<form method="post" action="/software/packages/{{ package.id }}/process-control" class="software-package-process-form">
|
||||
<label for="package_process_names">{{ t('software_packages.process_names') }}
|
||||
<input id="package_process_names" name="process_names" value="{{ manifest.process_control.process_names|join(', ') }}" placeholder="Greenshot.exe">
|
||||
<input id="package_process_names" name="process_names" value="{{ manifest.process_control.process_names|join(', ') }}" placeholder="ExampleApp.exe">
|
||||
</label>
|
||||
<small class="muted">{{ t('software_packages.process_names_help') }}</small>
|
||||
<label for="package_process_grace_seconds">{{ t('software_packages.process_grace_seconds') }}
|
||||
@@ -74,7 +75,7 @@
|
||||
<span>{{ t('software_packages.start_application') }}</span>
|
||||
</label>
|
||||
<label for="package_start_executable">{{ t('software_packages.start_executable') }}
|
||||
<input id="package_start_executable" name="executable" value="{{ manifest.post_install.executable }}" placeholder="C:\Program Files\Greenshot\Greenshot.exe">
|
||||
<input id="package_start_executable" name="executable" value="{{ manifest.post_install.executable }}" placeholder="C:\Program Files\ExampleApp\ExampleApp.exe">
|
||||
</label>
|
||||
<small class="muted">{{ t('software_packages.start_executable_help') }}</small>
|
||||
<label for="package_start_arguments">{{ t('software_packages.start_arguments') }}
|
||||
|
||||
@@ -7,10 +7,35 @@
|
||||
</div>
|
||||
<div class="setup-analyzer-actions">
|
||||
<a class="button" href="/software/setup-analyzer">{{ t('software_packages.new_from_analyzer') }}</a>
|
||||
<a class="button button-secondary" href="/software/setup-analyzer/profiles">{{ t('setup_profiles.manage') }}</a>
|
||||
<a class="button button-secondary" href="/software">{{ t('setup_analyzer.back_to_software') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="panel software-package-import-panel">
|
||||
<h2>{{ t('software_packages.import_title') }}</h2>
|
||||
<p class="muted">{{ t('software_packages.import_help') }}</p>
|
||||
<form method="post" action="/software/packages/import" enctype="multipart/form-data" class="software-package-import-form">
|
||||
<label for="software-package-import-file">{{ t('software_packages.import_file') }}</label>
|
||||
<div class="localized-file-picker" data-file-picker>
|
||||
<input class="localized-file-picker-input" id="software-package-import-file" type="file" name="package_file" accept=".ampkg,.zip" required data-file-picker-input>
|
||||
<button class="button button-secondary localized-file-picker-button" type="button" data-file-picker-button aria-controls="software-package-import-file">{{ t('common.choose_file') }}</button>
|
||||
<span class="localized-file-picker-name" data-file-picker-name data-empty-text="{{ t('common.no_file_selected') }}" aria-live="polite">{{ t('common.no_file_selected') }}</span>
|
||||
</div>
|
||||
<div class="software-package-import-options">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" name="confirm_scripts" value="1" required>
|
||||
<span>{{ t('software_packages.import_script_warning') }}</span>
|
||||
</label>
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" name="import_profile" value="1">
|
||||
<span>{{ t('software_packages.import_profile') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<button class="button" type="submit">{{ t('software_packages.import_button') }}</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="table-scroll management-table-scroll">
|
||||
<table class="data-table" data-storage-key="software-packages">
|
||||
@@ -37,8 +62,23 @@
|
||||
<td>{{ manifest.architecture or '—' }}</td>
|
||||
<td>{{ manifest.installer_type or '—' }}</td>
|
||||
<td>{{ human_size(row.storage_size) }}</td>
|
||||
<td>{% if row.storage_error %}<span class="job-status job-status-failed">{{ t('software_packages.storage_error') }}</span>{% elif package.enabled %}<span class="job-status job-status-success">{{ t('software_packages.enabled') }}</span>{% else %}<span class="job-status">{{ t('software_packages.disabled') }}</span>{% endif %}</td>
|
||||
<td><a class="button button-secondary button-small" href="/software/packages/{{ package.id }}">{{ t('software.open') }}</a></td>
|
||||
<td>{% if row.storage_error %}<span class="job-status job-status-failed" title="{{ row.storage_error }}">{{ t('software_packages.storage_error') }}</span>{% elif package.enabled %}<span class="job-status job-status-success">{{ t('software_packages.enabled') }}</span>{% else %}<span class="job-status">{{ t('software_packages.disabled') }}</span>{% endif %}</td>
|
||||
<td>
|
||||
{% if row.job_count %}
|
||||
{% set delete_confirm_text = t('software_packages.delete_confirm_with_jobs', package=package.name, count=row.job_count) %}
|
||||
{% else %}
|
||||
{% set delete_confirm_text = t('software_packages.delete_confirm', package=package.name) %}
|
||||
{% endif %}
|
||||
<div class="software-package-row-actions">
|
||||
<a class="button button-secondary button-small" href="/software/packages/{{ package.id }}">{{ t('software.open') }}</a>
|
||||
{% if not row.storage_error %}<a class="button button-secondary button-small" href="/software/packages/{{ package.id }}/export">{{ t('software_packages.export_button') }}</a>{% endif %}
|
||||
<form class="inline-form" method="post" action="/software/packages/{{ package.id }}/delete" onsubmit="return confirm({{ delete_confirm_text|tojson }});">
|
||||
<input type="hidden" name="return_to" value="overview">
|
||||
{% if row.job_count %}<input type="hidden" name="delete_jobs" value="1">{% endif %}
|
||||
<button class="button button-danger button-small" type="submit">{{ t('software_packages.delete_button_short') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="8">{{ t('software_packages.none') }}</td></tr>
|
||||
|
||||
Reference in New Issue
Block a user