Vastai-ConnectHub/app/admin/templates/joblog_list.html

315 lines
16 KiB
HTML

{% extends "sqladmin/list.html" %}
{% block content %}
<style>
.connecthub-retry-form {
display: inline;
margin: 0;
}
</style>
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="d-flex">
<div class="flex-grow-1 me-2">
<div class="card">
<div class="card-header">
<h3 class="card-title">{{ model_view.name_plural }}</h3>
<div class="ms-auto">
{% if model_view.can_export %}
{% if model_view.export_types | length > 1 %}
<div class="ms-3 d-inline-block dropdown">
<a href="#" class="btn btn-secondary dropdown-toggle" id="dropdownMenuButton1" data-bs-toggle="dropdown"
aria-expanded="false">
导出
</a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
{% for export_type in model_view.export_types %}
<li><a class="dropdown-item"
href="{{ url_for('admin:export', identity=model_view.identity, export_type=export_type) }}">{{
export_type | upper }}</a></li>
{% endfor %}
</ul>
</div>
{% elif model_view.export_types | length == 1 %}
<div class="ms-3 d-inline-block">
<a href="{{ url_for('admin:export', identity=model_view.identity, export_type=model_view.export_types[0]) }}"
class="btn btn-secondary">
导出
</a>
</div>
{% endif %}
{% endif %}
{% if model_view.can_create %}
<div class="ms-3 d-inline-block">
<a href="{{ url_for('admin:create', identity=model_view.identity) }}" class="btn btn-primary">
+ 新建{{ model_view.name }}
</a>
</div>
{% endif %}
</div>
</div>
{% if request.query_params.get('error') %}
<div class="alert alert-danger m-3" role="alert">
{{ request.query_params.get('error') }}
</div>
{% endif %}
<div class="card-body border-bottom py-3">
<div class="d-flex justify-content-between">
<div class="dropdown col-4">
<button {% if not model_view.can_delete and not model_view._custom_actions_in_list %} disabled {% endif %}
class="btn btn-light dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
操作
</button>
{% if model_view.can_delete or model_view._custom_actions_in_list %}
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
{% if model_view.can_delete %}
<a class="dropdown-item" id="action-delete" href="#" data-name="{{ model_view.name }}"
data-url="{{ url_for('admin:delete', identity=model_view.identity) }}" data-bs-toggle="modal"
data-bs-target="#modal-delete">删除所选</a>
{% endif %}
{% for custom_action, label in model_view._custom_actions_in_list.items() %}
{% if custom_action in model_view._custom_actions_confirmation %}
<a class="dropdown-item" id="action-customconfirm-{{ custom_action }}" href="#" data-bs-toggle="modal"
data-bs-target="#modal-confirmation-{{ custom_action }}">
{{ label }}
</a>
{% else %}
<a class="dropdown-item" id="action-custom-{{ custom_action }}" href="#"
data-url="{{ model_view._url_for_action(request, custom_action) }}">
{{ label }}
</a>
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% if model_view.column_searchable_list %}
<div class="col-md-4 text-muted">
<div class="input-group">
<input id="search-input" type="text" class="form-control"
placeholder="搜索:{{ model_view.search_placeholder() }}"
value="{{ request.query_params.get('search', '') }}">
<button id="search-button" class="btn" type="button">搜索</button>
<button id="search-reset" class="btn" type="button" {% if not request.query_params.get('search')
%}disabled{% endif %}><i class="fa-solid fa-times"></i></button>
</div>
</div>
{% endif %}
</div>
</div>
<div class="table-responsive">
<table class="table card-table table-vcenter text-nowrap">
<thead>
<tr>
<th class="w-1"><input class="form-check-input m-0 align-middle" type="checkbox" aria-label="Select all"
id="select-all"></th>
<th class="w-1"></th>
{% for name in model_view._list_prop_names %}
{% set label = model_view._column_labels.get(name, name) %}
<th>
{% if name in model_view._sort_fields %}
{% if request.query_params.get("sortBy") == name and request.query_params.get("sort") == "asc" %}
<a href="{{ request.url.include_query_params(sort='desc') }}"><i class="fa-solid fa-arrow-up"></i> {{
label }}</a>
{% elif request.query_params.get("sortBy") == name and request.query_params.get("sort") == "desc" %}
<a href="{{ request.url.include_query_params(sort='asc') }}"><i class="fa-solid fa-arrow-down"></i> {{ label
}}</a>
{% else %}
<a href="{{ request.url.include_query_params(sortBy=name, sort='asc') }}">{{ label }}</a>
{% endif %}
{% else %}
{{ label }}
{% endif %}
</th>
{% endfor %}
<th>重试</th>
</tr>
</thead>
<tbody>
{% for row in pagination.rows %}
<tr>
<td>
<input type="hidden" value="{{ get_object_identifier(row) }}">
<input class="form-check-input m-0 align-middle select-box" type="checkbox" aria-label="Select item">
</td>
<td class="text-end">
{% if model_view.can_view_details %}
<a href="{{ model_view._build_url_for('admin:details', request, row) }}" data-bs-toggle="tooltip"
data-bs-placement="top" title="View">
<span class="me-1"><i class="fa-solid fa-eye"></i></span>
</a>
{% endif %}
{% if model_view.can_edit %}
<a href="{{ model_view._build_url_for('admin:edit', request, row) }}" data-bs-toggle="tooltip"
data-bs-placement="top" title="Edit">
<span class="me-1"><i class="fa-solid fa-pen-to-square"></i></span>
</a>
{% endif %}
{% if model_view.can_delete %}
<a href="#" data-name="{{ model_view.name }}" data-pk="{{ get_object_identifier(row) }}"
data-url="{{ model_view._url_for_delete(request, row) }}" data-bs-toggle="modal"
data-bs-target="#modal-delete" title="Delete">
<span class="me-1"><i class="fa-solid fa-trash"></i></span>
</a>
{% endif %}
</td>
{% for name in model_view._list_prop_names %}
{% set value, formatted_value = model_view.get_list_value(row, name) %}
{% if name in model_view._relation_names %}
{% if is_list( value ) %}
<td>
{% for elem, formatted_elem in zip(value, formatted_value) %}
{% if model_view.show_compact_lists %}
<a href="{{ model_view._build_url_for('admin:details', request, elem) }}">({{ formatted_elem }})</a>
{% else %}
<a href="{{ model_view._build_url_for('admin:details', request, elem) }}">{{ formatted_elem }}</a><br/>
{% endif %}
{% endfor %}
</td>
{% else %}
<td><a href="{{ model_view._url_for_details_with_prop(request, row, name) }}">{{ formatted_value }}</a></td>
{% endif %}
{% else %}
<td>{{ formatted_value }}</td>
{% endif %}
{% endfor %}
<td>
<form class="connecthub-retry-form" method="post" action="/admin/joblogs/{{ get_object_identifier(row) }}/retry" onsubmit="return confirm('确认重试该任务日志?');">
<button type="submit" class="btn btn-warning btn-sm">重试</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="card-footer d-flex justify-content-between align-items-center gap-2">
<p class="m-0 text-muted">显示 <span>{{ ((pagination.page - 1) * pagination.page_size) + 1 }}</span>
<span>{{ min(pagination.page * pagination.page_size, pagination.count) }}</span>,共 <span>{{ pagination.count
}}</span>
</p>
<ul class="pagination m-0 ms-auto">
<li class="page-item {% if not pagination.has_previous %}disabled{% endif %}">
{% if pagination.has_previous %}
<a class="page-link" href="{{ pagination.previous_page.url }}">
{% else %}
<a class="page-link" href="#">
{% endif %}
<i class="fa-solid fa-chevron-left"></i>
上一页
</a>
</li>
{% for page_control in pagination.page_controls %}
<li class="page-item {% if page_control.number == pagination.page %}active{% endif %}"><a class="page-link"
href="{{ page_control.url }}">{{ page_control.number }}</a></li>
{% endfor %}
<li class="page-item {% if not pagination.has_next %}disabled{% endif %}">
{% if pagination.has_next %}
<a class="page-link" href="{{ pagination.next_page.url }}">
{% else %}
<a class="page-link" href="#">
{% endif %}
下一页
<i class="fa-solid fa-chevron-right"></i>
</a>
</li>
</ul>
<div class="dropdown text-muted">
每页显示
<a href="#" class="btn btn-sm btn-light dropdown-toggle" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
{{ request.query_params.get("pageSize") or model_view.page_size }} / 页
</a>
<div class="dropdown-menu">
{% for page_size_option in model_view.page_size_options %}
<a class="dropdown-item" href="{{ request.url.include_query_params(pageSize=page_size_option, page=pagination.resize(page_size_option).page) }}">
{{ page_size_option }} / 页
</a>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
{% if model_view.get_filters() %}
<div class="col-md-3" style="width: 300px; flex-shrink: 0;">
<div id="filter-sidebar" class="card">
<div class="card-header">
<h3 class="card-title">筛选</h3>
</div>
<div class="card-body">
{% for filter in model_view.get_filters() %}
{% if filter.has_operator %}
<div class="mb-3">
<div class="fw-bold text-truncate">{{ filter.title }}</div>
<div>
{% set current_filter = request.query_params.get(filter.parameter_name, '') %}
{% set current_op = request.query_params.get(filter.parameter_name + '_op', '') %}
{% if current_filter %}
<div class="mb-2 text-muted small">
当前:{{ current_op }} {{ current_filter }}
<a href="{{ request.url.remove_query_params(filter.parameter_name).remove_query_params(filter.parameter_name + '_op') }}" class="text-decoration-none">[清除]</a>
</div>
{% endif %}
<form method="get" class="d-flex flex-column" style="gap: 8px;">
{% for key, value in request.query_params.items() %}
{% if key != filter.parameter_name and key != filter.parameter_name + '_op' %}
<input type="hidden" name="{{ key }}" value="{{ value }}">
{% endif %}
{% endfor %}
<select name="{{ filter.parameter_name }}_op" class="form-select form-select-sm" required>
<option value="">选择操作...</option>
{% for op_value, op_label in filter.get_operation_options_for_model(model_view.model) %}
<option value="{{ op_value }}" {% if current_op == op_value %}selected{% endif %}>{{ op_label }}</option>
{% endfor %}
</select>
<input type="text"
name="{{ filter.parameter_name }}"
placeholder="Enter value"
class="form-control form-control-sm"
value="{{ current_filter }}"
required>
<button type="submit" class="btn btn-sm btn-outline-primary">应用筛选</button>
</form>
</div>
</div>
{% else %}
<div class="mb-3">
<div class="fw-bold text-truncate">{{ filter.title }}</div>
<div>
{% for lookup in filter.lookups(request, model_view.model, model_view._run_arbitrary_query) %}
<a href="{{ request.url.include_query_params(**{filter.parameter_name: lookup[0]}) }}" class="d-block text-decoration-none text-truncate">
{{ lookup[1] }}
</a>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
{% if model_view.can_delete %}
{% include 'sqladmin/modals/delete.html' %}
{% endif %}
{% for custom_action in model_view._custom_actions_in_list %}
{% if custom_action in model_view._custom_actions_confirmation %}
{% with confirmation_message = model_view._custom_actions_confirmation[custom_action], custom_action=custom_action,
url=model_view._url_for_action(request, custom_action) %}
{% include 'sqladmin/modals/list_action_confirmation.html' %}
{% endwith %}
{% endif %}
{% endfor %}
</div>
{% endblock %}