주시
1
1
포크
이미 mt5-manager을(를) 포크했습니다
1
원본 프로젝트 antekov/mt5-manager
mt5-manager/templates/index.html
Yuriy Bykov Yuriy Bykov 779efef59f Improve terminal settings and operation notifications
Separate configuration saving from connection testing, preserve terminal process state after tests, and support deleting stopped instances.

Simplify account fields and optional servers.dat uploads. Show operation progress per terminal and dismiss results after five seconds with a circular countdown.

Update documentation and tests for the revised behavior.
2026-11-01 19:40:01 +03:00
107 라인
8.7 KiB
HTML
{% extends "base.html" %}
<!-- index.html, version 0.6.0 -->
{% block title %}Терминалы — MT5 Manager{% endblock %}
{% block content %}
<header class="page-heading">
<div><h1>Терминалы</h1><p class="page-description">Экземпляры MetaTrader 5 и состояние торговых счетов</p></div>
<button type="button" class="button button-primary" data-dialog-open="create-dialog">
<svg class="icon"><use href="#icon-plus"/></svg>Новый терминал
</button>
</header>
<div id="operation-message" role="status" aria-live="polite" class="notice is-hidden"></div>
<section aria-label="Список терминалов">
<div class="list-toolbar">
<div class="filters" role="group" aria-label="Фильтр состояния">
<button class="filter active" data-filter="all" aria-pressed="true">Все <span id="count-all">{{ instances | length }}</span></button>
<button class="filter" data-filter="active" aria-pressed="false">Запущены <span id="count-active">—</span></button>
<button class="filter" data-filter="stopped" aria-pressed="false">Остановлены <span id="count-stopped">—</span></button>
</div>
<label class="search-field"><svg class="icon"><use href="#icon-search"/></svg>
<input type="search" id="terminal-search" placeholder="Найти терминал" aria-label="Найти терминал">
</label>
</div>
<div id="terminal-list" class="terminal-grid">
{% for folder, terminal in instances.items() %}
<article class="terminal-card loading-card" data-folder="{{ folder }}" data-state="stopped">
<header class="terminal-header">
<span class="broker-mark"><span class="server server-{{ terminal.server }}" aria-hidden="true"></span></span>
<div class="terminal-identity">
<h2>{{ terminal.name or folder }}</h2>
<p><span class="account">Счёт не задан</span><span class="account-separator">·</span><span class="account-server">{{ terminal.server or 'Без подключения' }}</span></p>
</div>
<a class="icon-button terminal-settings" href="/settings#account-{{ folder | urlencode }}" aria-label="Настройки {{ terminal.name or folder }}" title="Настроить счёт">
<svg class="icon"><use href="#icon-settings"/></svg>
</a>
</header>
<div class="terminal-state-row"><span class="status-badge" data-tone="neutral"><span class="status-dot"></span><span class="description">Получаем состояние</span></span>{% if terminal.name and terminal.name != folder %}<span class="terminal-folder">{{ folder }}</span>{% endif %}</div>
<div class="terminal-metrics">
<div class="metric"><span class="metric-label">Баланс <span class="currency"></span></span><span class="metric-value balance">—</span></div>
<div class="metric"><span class="metric-label">Средства</span><span class="metric-value equity">—</span></div>
<div class="metric metric-profit"><span class="metric-label">Прибыль</span><div class="profit-line"><span class="metric-value profit">—</span><span class="profit-pct is-hidden">—</span></div></div>
<div class="metric"><span class="metric-label">Маржа</span><span class="metric-value margin">—</span></div>
</div>
<div class="terminal-operation notice is-hidden" role="status" aria-live="polite"></div>
<footer class="terminal-footer">
<span class="update-time"><svg class="icon"><use href="#icon-clock"/></svg><span class="time">Ожидает запуска</span></span>
<div class="terminal-actions">
<button type="button" class="button button-soft button-small btn-start" data-folder="{{ folder }}" data-action="start" aria-label="Запустить {{ terminal.name or folder }}">
<svg class="icon"><use href="#icon-play"/></svg><span>Запустить</span>
</button>
<button type="button" class="button button-secondary button-small btn-stop" data-folder="{{ folder }}" data-action="stop" aria-label="Остановить {{ terminal.name or folder }}" disabled>
<svg class="icon"><use href="#icon-stop"/></svg><span>Стоп</span>
</button>
</div>
</footer>
</article>
{% endfor %}
</div>
<div id="terminal-empty" class="empty-state {% if instances %}is-hidden{% endif %}">
<span class="empty-icon"><svg class="icon"><use href="#icon-terminal"/></svg></span>
<h2>{% if instances %}Ничего не найдено{% else %}Здесь будут ваши терминалы{% endif %}</h2>
<p>{% if instances %}Измените запрос или выберите другое состояние.{% else %}Подготовьте файлы в настройках и создайте первый экземпляр.{% endif %}</p>
</div>
</section>
<dialog id="create-dialog" class="modal-dialog" aria-labelledby="create-title">
<header class="modal-header"><div><h2 id="create-title">Новый терминал</h2><p>Отдельный экземпляр MetaTrader 5</p></div>
<button type="button" class="icon-button" data-dialog-close aria-label="Закрыть"><svg class="icon"><use href="#icon-close"/></svg></button>
</header>
<form id="create-terminal">
<div class="modal-body">
<div class="form-feedback notice notice-danger is-hidden" role="alert"></div>
<div class="form-grid">
<label class="field" for="new-folder"><span>Имя папки экземпляра</span><input id="new-folder" name="folder" maxlength="80" required autocomplete="off" autofocus></label>
<label class="field" for="new-name"><span>Отображаемое имя</span><input id="new-name" name="name" placeholder="Как имя папки"></label>
</div>
<details class="form-section" open>
<summary><svg class="icon disclosure-icon"><use href="#icon-chevron"/></svg><span>Подключение к счёту<span class="summary-hint">Необязательно</span></span></summary>
<div class="form-section-body">
<div class="form-grid">
<label class="field" for="new-login"><span>Логин счёта</span><input id="new-login" name="login" inputmode="numeric" autocomplete="off" placeholder="Номер счёта"></label>
<label class="field" for="new-password"><span>Пароль счёта</span><input id="new-password" name="password" type="password" autocomplete="new-password" placeholder="Пароль для подключения"></label>
<label class="field" for="new-server"><span>Торговый сервер</span><input id="new-server" name="server" autocomplete="off" placeholder="Например, Broker-Demo"></label>
<div class="account-server-upload">
<div class="file-choice">
<label class="button button-secondary button-small"><input id="new-servers" class="file-input" name="servers_file" type="file" accept=".dat" aria-label="Выбрать servers.dat" aria-describedby="new-servers-help">Выбрать servers.dat</label>
</div>
<div id="new-servers-selection" class="account-selected-file is-hidden">
<span id="new-servers-name" class="file-selected" aria-live="polite"></span>
<button id="clear-new-servers" type="button" class="button button-text button-small" aria-label="Отменить выбор servers.dat">Отменить</button>
</div>
</div>
</div>
<p class="field-help">Можно оставить реквизиты пустыми и настроить счёт позже.</p>
<p id="new-servers-help" class="field-help">При необходимости выберите servers.dat из папки config вашего локального терминала с нужным брокером. Файл будет скопирован только в создаваемый экземпляр. Загрузка необязательна.</p>
</div>
</details>
<div class="form-note"><svg class="icon"><use href="#icon-folder"/></svg><span>EXE берутся из исходной установки, выбранной в <a href="/settings">настройках</a>. Сервис будет подготовлен автоматически.</span></div>
</div>
<footer class="modal-footer"><button type="button" class="button button-text" data-dialog-close>Отмена</button><button class="button button-primary" type="submit">Создать и запустить</button></footer>
</form>
</dialog>
{% endblock %}
{% block scripts %}
<script>const terminals = {{ instances | list | tojson }};</script>
<script src="/static/script.js?v=0.7.0"></script>
{% endblock %}