Files
RoleForge/app/templates/role-view.xhtml
Sergey Antropoff 01d598eea5 - Админка: настройка pull-реестра (Hub / Harbor / Nexus) в БД, шифрование секретов;
обновлён /admin/config и API для os_registry.
- Molecule/раннер: env из конфигурации, ensure roleforge-os (ensure_roleforge_os.yml),
  os_registry_pull и доработки executors / runner / create.yml.
- /admin/os-images: выбор реестра, buildx (в т.ч. split amd64+arm64 + imagetools),
  опция --no-cache, стрим логов; domain.py: план команд build, ретраи push.
- UI: брендинг (app_name, app_tagline) из app_config через get_ui_branding_context;
  base.xhtml, role-create / role-view, core.js, pages-main, стили.
- Dockerfiles: требование Python ≥3.9 (assert), доработки alt9/astra/debian9/ubuntu20
  и др.; новые Dockerfile.arm64 для centos7/centos8.
- Конфиг: .env.example, config.py, pyproject.toml.
2026-05-06 07:52:29 +03:00

147 lines
8.5 KiB
HTML

{% extends "base.xhtml" %}
{% from "macros/page-hero.xhtml" import page_hero %}
{% block content %}
<div class="dashboard-page roles-page" data-role-id="{{ role_id }}">
{% call page_hero("Library", "Role Details", "Edit metadata and role files from the catalog; save to persist.") %}
<div class="dashboard-hero-actions dashboard-hero-actions--roles" aria-label="Role actions">
<button type="button" class="btn-danger" id="role-view-delete-btn" hidden="hidden">Delete</button>
<button type="button" class="cta-button" id="role-view-fork-btn" hidden="hidden">Fork to edit</button>
<button type="button" class="cta-button" id="role-view-hero-export-btn" aria-label="Export role as ZIP archive">
Export
</button>
</div>
{% endcall %}
<section class="dashboard-panel dashboard-panel--primary role-view-tabbed-shell">
<div class="role-view-tabs" role="tablist" aria-label="Role sections">
<button type="button" class="role-view-tab" role="tab" id="role-tab-trigger-details" aria-selected="true" aria-controls="role-tab-panel-details">Role details</button>
<button type="button" class="role-view-tab" role="tab" id="role-tab-trigger-catalog" aria-selected="false" aria-controls="role-tab-panel-catalog" tabindex="-1">Role files catalog</button>
</div>
<div class="role-view-tabbed-panels">
<section id="role-tab-panel-details" class="role-view-tab-panel" role="tabpanel" aria-labelledby="role-tab-trigger-details">
<div class="dashboard-panel-h">
<div>
<h2 class="dashboard-panel-title">Role details</h2>
<p class="dashboard-panel-sub">Name, category, source and description. Save applies metadata and files from the catalog.</p>
</div>
</div>
<form id="role-view-form" class="roles-form-grid">
<label class="schema-field">
<span class="schema-field__label">Role Name</span>
<input type="text" id="role-view-name" required="required" />
</label>
<label class="schema-field">
<span class="schema-field__label">Category</span>
<select id="role-view-category">
<option value="">Uncategorized</option>
</select>
</label>
<label class="schema-field">
<span class="schema-field__label">Source Type</span>
<select id="role-view-source-type">
<option value="inline">inline</option>
<option value="git">git</option>
<option value="galaxy">galaxy</option>
</select>
</label>
<label class="schema-field">
<span class="schema-field__label">Source Ref</span>
<input type="text" id="role-view-source-ref" />
</label>
<label class="schema-field schema-field--wide">
<span class="schema-field__label">Description</span>
<textarea id="role-view-description" rows="5" placeholder="Describe what this role does…"></textarea>
</label>
<label class="schema-field schema-field--wide">
<span class="schema-field__label">Tags</span>
<input type="text" id="role-view-tags" placeholder="e.g. nginx, ssl, web — comma-separated" autocomplete="off" />
</label>
<div class="schema-field schema-field--wide" id="role-os-families-wrap">
<span class="schema-field__label">Target OS families</span>
<div class="role-os-family-grid" id="role-os-family-grid" aria-label="Target operating system families"></div>
<p class="muted small-note" style="margin:6px 0 0">Optional. Shown as badges in the role catalog; pick all that apply.</p>
</div>
<div class="schema-field schema-field--wide role-visibility-field">
<span class="schema-field__label" id="role-visibility-label">Who can see this role</span>
<div class="radio-segment-group role-visibility-segments" role="radiogroup" aria-labelledby="role-visibility-label">
<label class="radio-segment">
<input type="radio" name="role-view-visibility" value="public" />
<span class="radio-segment-face">
<span class="radio-segment-title radio-segment-title--with-icon">
<i class="fa-solid fa-globe radio-segment-icon" aria-hidden="true"></i>
<span>Public</span>
</span>
<span class="radio-segment-desc">Listed for everyone; anyone can browse or fork.</span>
</span>
</label>
<label class="radio-segment">
<input type="radio" name="role-view-visibility" value="team" />
<span class="radio-segment-face">
<span class="radio-segment-title radio-segment-title--with-icon">
<i class="fa-solid fa-users radio-segment-icon" aria-hidden="true"></i>
<span>Team</span>
</span>
<span class="radio-segment-desc">Visible to members of the team you choose.</span>
</span>
</label>
<label class="radio-segment">
<input type="radio" name="role-view-visibility" value="personal" checked="checked" />
<span class="radio-segment-face">
<span class="radio-segment-title radio-segment-title--with-icon">
<i class="fa-solid fa-user-shield radio-segment-icon" aria-hidden="true"></i>
<span>Personal</span>
</span>
<span class="radio-segment-desc">Only you — not listed in the public library.</span>
</span>
</label>
</div>
<p class="muted small-note role-visibility-footnote">Personal roles can become Public via “Who can see this role”. Public roles can only be deleted by an administrator; personal roles can be deleted by you or an administrator.</p>
</div>
<div class="schema-field schema-field--wide role-team-picker-field" id="role-team-picker-wrap" hidden="hidden">
<span class="schema-field__label">Team</span>
<div class="role-team-picker-actions">
<span id="role-team-display" class="role-team-display role-team-display--summary muted"></span>
<button type="button" class="cta-button role-team-picker-open-btn" id="role-team-choose-btn">
Choose team…
</button>
</div>
<p class="muted small-note" style="margin: 10px 0 0">Only teams you belong to (active membership) are listed.</p>
</div>
</form>
</section>
<section id="role-tab-panel-catalog" class="role-view-tab-panel" role="tabpanel" aria-labelledby="role-tab-trigger-catalog" hidden="hidden">
<div class="dashboard-panel-h">
<div>
<h2 class="dashboard-panel-title">Role files catalog</h2>
<p class="dashboard-panel-sub">Folders mirror Ansible layout. Open files from the tree; use icons to add a folder or file.</p>
</div>
<div class="role-file-catalog-toolbar">
<button type="button" class="btn-icon btn-icon--add" id="role-view-add-folder-btn" data-tooltip="Add folder" aria-label="Add folder">
<i class="fa-solid fa-folder-plus" aria-hidden="true"></i>
</button>
<button type="button" class="btn-icon btn-icon--export" id="role-view-add-file-btn" data-tooltip="Add file" aria-label="Add file">
<i class="fa-solid fa-file-circle-plus" aria-hidden="true"></i>
</button>
<button type="button" class="btn-icon btn-icon--open" id="role-view-files-upload-btn" data-tooltip="Upload files into files/" aria-label="Upload files into files directory">
<i class="fa-solid fa-upload" aria-hidden="true"></i>
</button>
</div>
</div>
<div id="role-view-catalog" class="role-file-catalog" aria-label="Role files tree"></div>
</section>
</div>
</section>
<div class="roles-page-bottom-actions">
<button type="submit" form="role-view-form" class="cta-button">Save</button>
<button type="button" class="btn-muted" id="role-view-test-btn">Test</button>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/theme/dracula.min.css" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/yaml/yaml.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/javascript/javascript.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/edit/matchbrackets.min.js"></script>
{% endblock %}