flask-admin-tabler 2026.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. flask_admin_tabler-2026.2.1/LICENSE +21 -0
  2. flask_admin_tabler-2026.2.1/PKG-INFO +111 -0
  3. flask_admin_tabler-2026.2.1/README.md +61 -0
  4. flask_admin_tabler-2026.2.1/flask_admin_tabler/__init__.py +3 -0
  5. flask_admin_tabler-2026.2.1/flask_admin_tabler/static/admin/css/tabler/admin.css +74 -0
  6. flask_admin_tabler-2026.2.1/flask_admin_tabler/static/admin/css/tabler/rediscli.css +48 -0
  7. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/actions.html +38 -0
  8. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/base.html +115 -0
  9. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/file/form.html +9 -0
  10. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/file/list.html +195 -0
  11. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/file/modals/form.html +19 -0
  12. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/index.html +4 -0
  13. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/layout.html +103 -0
  14. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/lib.html +293 -0
  15. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/master.html +1 -0
  16. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/create.html +30 -0
  17. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/details.html +53 -0
  18. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/edit.html +40 -0
  19. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/inline_field_list.html +15 -0
  20. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/inline_form.html +4 -0
  21. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/inline_list_base.html +45 -0
  22. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/layout.html +110 -0
  23. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/list.html +198 -0
  24. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/modals/create.html +26 -0
  25. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/modals/details.html +40 -0
  26. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/modals/edit.html +27 -0
  27. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/model/row_actions.html +38 -0
  28. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/rediscli/console.html +27 -0
  29. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/rediscli/response.html +32 -0
  30. flask_admin_tabler-2026.2.1/flask_admin_tabler/templates/tabler/admin/static.html +3 -0
  31. flask_admin_tabler-2026.2.1/flask_admin_tabler/theme.py +55 -0
  32. flask_admin_tabler-2026.2.1/pyproject.toml +86 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mario Hernandez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,111 @@
1
+ Metadata-Version: 2.4
2
+ Name: flask-admin-tabler
3
+ Version: 2026.2.1
4
+ Summary: Tabler UI theme for Flask-Admin
5
+ License: MIT License
6
+
7
+ Copyright (c) 2026 Mario Hernandez
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+ License-File: LICENSE
27
+ Keywords: flask,flask-admin,tabler,admin-interface,theme,template
28
+ Requires-Python: >=3.10,<4.0
29
+ Classifier: Development Status :: 4 - Beta
30
+ Classifier: Environment :: Web Environment
31
+ Classifier: Intended Audience :: Developers
32
+ Classifier: License :: OSI Approved :: BSD License
33
+ Classifier: Operating System :: OS Independent
34
+ Classifier: Programming Language :: Python
35
+ Classifier: Programming Language :: Python :: 3
36
+ Classifier: Programming Language :: Python :: 3.10
37
+ Classifier: Programming Language :: Python :: 3.11
38
+ Classifier: Programming Language :: Python :: 3.12
39
+ Classifier: Programming Language :: Python :: 3.13
40
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
41
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
42
+ Provides-Extra: dev
43
+ Requires-Dist: black ; extra == "dev"
44
+ Requires-Dist: flask-admin (>=2.0.2)
45
+ Requires-Dist: isort ; extra == "dev"
46
+ Requires-Dist: pre-commit ; extra == "dev"
47
+ Project-URL: Source, https://github.com/mariofix/flask-admin-tablerui
48
+ Description-Content-Type: text/markdown
49
+
50
+ # flask-admin-tabler
51
+
52
+ A [Tabler UI](https://tabler.io/) theme for [Flask-Admin](https://github.com/pallets-eco/flask-admin).
53
+
54
+ ## Installation
55
+
56
+ ```shell
57
+ pip install flask-admin-tabler
58
+ ```
59
+
60
+ ## Usage
61
+
62
+ Call `theme.init_app(app)` **before** creating the `Admin` instance so that the
63
+ Tabler templates are registered with higher priority than Flask-Admin's default
64
+ Bootstrap ones.
65
+
66
+ ```python
67
+ from flask import Flask
68
+ from flask_admin import Admin
69
+ from flask_admin_tabler import TablerTheme
70
+
71
+ app = Flask(__name__)
72
+ app.config["SECRET_KEY"] = "change-me"
73
+
74
+ theme = TablerTheme()
75
+ theme.init_app(app) # must come before Admin(app, ...)
76
+
77
+ admin = Admin(app, name="My App", theme=theme)
78
+ ```
79
+
80
+ That's it — navigating to `/admin/` will now render the Tabler UI instead of
81
+ the default Bootswatch theme.
82
+
83
+ A fully runnable example (including a SQLAlchemy model and sample data) is
84
+ available in [`examples/quickstart.py`](examples/quickstart.py):
85
+
86
+ ```shell
87
+ pip install flask-admin-tabler flask-sqlalchemy
88
+ python examples/quickstart.py
89
+ # open http://127.0.0.1:5000/admin/
90
+ ```
91
+
92
+ ## How it works
93
+
94
+ `TablerTheme.init_app(app)` registers a Flask blueprint named
95
+ `flask_admin_tabler` that:
96
+
97
+ 1. **Templates** — exposes `flask_admin_tabler/templates/tabler/` as a template
98
+ folder. Because this blueprint is registered *before* Flask-Admin's admin
99
+ blueprint, Flask resolves `admin/base.html` (and all other admin templates)
100
+ from here first.
101
+ 2. **Static files** — serves the small amount of theme-specific CSS (e.g.
102
+ `admin/css/tabler/admin.css`) at `/static/flask_admin_tabler/`.
103
+
104
+ Tabler's core CSS and JS are loaded from the jsDelivr CDN — no local copies
105
+ needed.
106
+
107
+ ## Requirements
108
+
109
+ - Python ≥ 3.10
110
+ - flask-admin ≥ 2.0.2
111
+
@@ -0,0 +1,61 @@
1
+ # flask-admin-tabler
2
+
3
+ A [Tabler UI](https://tabler.io/) theme for [Flask-Admin](https://github.com/pallets-eco/flask-admin).
4
+
5
+ ## Installation
6
+
7
+ ```shell
8
+ pip install flask-admin-tabler
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ Call `theme.init_app(app)` **before** creating the `Admin` instance so that the
14
+ Tabler templates are registered with higher priority than Flask-Admin's default
15
+ Bootstrap ones.
16
+
17
+ ```python
18
+ from flask import Flask
19
+ from flask_admin import Admin
20
+ from flask_admin_tabler import TablerTheme
21
+
22
+ app = Flask(__name__)
23
+ app.config["SECRET_KEY"] = "change-me"
24
+
25
+ theme = TablerTheme()
26
+ theme.init_app(app) # must come before Admin(app, ...)
27
+
28
+ admin = Admin(app, name="My App", theme=theme)
29
+ ```
30
+
31
+ That's it — navigating to `/admin/` will now render the Tabler UI instead of
32
+ the default Bootswatch theme.
33
+
34
+ A fully runnable example (including a SQLAlchemy model and sample data) is
35
+ available in [`examples/quickstart.py`](examples/quickstart.py):
36
+
37
+ ```shell
38
+ pip install flask-admin-tabler flask-sqlalchemy
39
+ python examples/quickstart.py
40
+ # open http://127.0.0.1:5000/admin/
41
+ ```
42
+
43
+ ## How it works
44
+
45
+ `TablerTheme.init_app(app)` registers a Flask blueprint named
46
+ `flask_admin_tabler` that:
47
+
48
+ 1. **Templates** — exposes `flask_admin_tabler/templates/tabler/` as a template
49
+ folder. Because this blueprint is registered *before* Flask-Admin's admin
50
+ blueprint, Flask resolves `admin/base.html` (and all other admin templates)
51
+ from here first.
52
+ 2. **Static files** — serves the small amount of theme-specific CSS (e.g.
53
+ `admin/css/tabler/admin.css`) at `/static/flask_admin_tabler/`.
54
+
55
+ Tabler's core CSS and JS are loaded from the jsDelivr CDN — no local copies
56
+ needed.
57
+
58
+ ## Requirements
59
+
60
+ - Python ≥ 3.10
61
+ - flask-admin ≥ 2.0.2
@@ -0,0 +1,3 @@
1
+ from flask_admin_tabler.theme import TablerTheme
2
+
3
+ __all__ = ["TablerTheme"]
@@ -0,0 +1,74 @@
1
+ /* Flask-Admin Tabler theme custom styles */
2
+
3
+ /* List view action buttons */
4
+ td.list-buttons-column {
5
+ white-space: nowrap;
6
+ width: 1%;
7
+ }
8
+
9
+ a.icon,
10
+ form.icon {
11
+ display: inline-block;
12
+ padding: 0 2px;
13
+ }
14
+
15
+ form.icon button {
16
+ background: none;
17
+ border: none;
18
+ cursor: pointer;
19
+ padding: 0;
20
+ color: inherit;
21
+ }
22
+
23
+ form.icon button:hover,
24
+ a.icon:hover {
25
+ color: var(--tblr-primary);
26
+ }
27
+
28
+ /* Inline form fields */
29
+ .inline-field-list .inline-field {
30
+ margin-bottom: 1rem;
31
+ }
32
+
33
+ /* Filter form table */
34
+ table.filters {
35
+ width: 100%;
36
+ }
37
+
38
+ /* Model list checkbox column */
39
+ .list-checkbox-column {
40
+ width: 1%;
41
+ white-space: nowrap;
42
+ }
43
+
44
+ /* Submit row spacing */
45
+ .submit-row {
46
+ display: flex;
47
+ gap: 0.5rem;
48
+ flex-wrap: wrap;
49
+ }
50
+
51
+ /* Admin form fieldset */
52
+ .admin-form fieldset {
53
+ border: none;
54
+ padding: 0;
55
+ margin: 0;
56
+ }
57
+
58
+ /* Select2 adjustments for Tabler */
59
+ .select2-container .select2-selection--single {
60
+ height: calc(1.5em + 0.75rem + 2px);
61
+ }
62
+
63
+ .select2-container--default .select2-selection--single .select2-selection__rendered {
64
+ line-height: calc(1.5em + 0.75rem);
65
+ }
66
+
67
+ .select2-container--default .select2-selection--single .select2-selection__arrow {
68
+ height: calc(1.5em + 0.75rem);
69
+ }
70
+
71
+ /* Searchable table filter */
72
+ tr.hidden-by-filter {
73
+ display: none;
74
+ }
@@ -0,0 +1,48 @@
1
+ .console {
2
+ position: relative;
3
+ width: 100%;
4
+ min-height: 400px;
5
+ }
6
+
7
+ .console-container {
8
+ border-radius: 4px;
9
+ position: absolute;
10
+ border: 1px solid #d4d4d4;
11
+ padding: 2px;
12
+ overflow: scroll;
13
+ top: 2px;
14
+ left: 2px;
15
+ right: 2px;
16
+ bottom: 5em;
17
+ }
18
+
19
+ .console-line {
20
+ position: absolute;
21
+ left: 2px;
22
+ right: 2px;
23
+ bottom: 2px;
24
+ }
25
+
26
+ .console-line input {
27
+ width: 100%;
28
+ box-sizing: border-box;
29
+ -moz-box-sizing: border-box;
30
+ -webkit-box-sizing: border-box;
31
+ height: 2em;
32
+ }
33
+
34
+ .console .cmd {
35
+ background-color: #f5f5f5;
36
+ padding: 2px;
37
+ margin: 1px;
38
+ }
39
+
40
+ .console .response {
41
+ background-color: #f0f0f0;
42
+ padding: 2px;
43
+ margin: 1px;
44
+ }
45
+
46
+ .console .error {
47
+ color: red;
48
+ }
@@ -0,0 +1,38 @@
1
+ {% import 'admin/static.html' as admin_static with context %}
2
+
3
+ {% macro dropdown(actions, btn_class='nav-link dropdown-toggle') -%}
4
+ <a class="{{ btn_class }}" data-bs-toggle="dropdown" href="javascript:void(0)" role="button" aria-haspopup="true"
5
+ aria-expanded="false">{{ _gettext('With selected') }}</a>
6
+ <div class="dropdown-menu">
7
+ {% for p in actions %}
8
+ <a class="dropdown-item" href="javascript:void(0)"
9
+ onclick="return modelActions.execute('{{ p[0] }}');">{{ _gettext(p[1]) }}</a>
10
+ {% endfor %}
11
+ </div>
12
+ {% endmacro %}
13
+
14
+ {% macro form(actions, url) %}
15
+ {% if actions %}
16
+ <form id="action_form" action="{{ url }}" method="POST" class="d-none">
17
+ {% if action_form.csrf_token is defined and action_form.csrf_token %}
18
+ {{ action_form.csrf_token }}
19
+ {% elif csrf_token is defined and csrf_token %}
20
+ <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
21
+ {% endif %}
22
+ {% if return_url is defined and return_url %}
23
+ {{ action_form.url(value=return_url) }}
24
+ {% else %}
25
+ {{ action_form.url() }}
26
+ {% endif %}
27
+ {{ action_form.action() }}
28
+ </form>
29
+ {% endif %}
30
+ {% endmacro %}
31
+
32
+ {% macro script(message, actions, actions_confirmation) %}
33
+ {% if actions %}
34
+ <div id="actions-confirmation-data" class="d-none">{{ actions_confirmation|tojson|safe }}</div>
35
+ <div id="message-data" class="d-none">{{ message|tojson|safe }}</div>
36
+ <script {{ admin_csp_nonce_attribute }} src="{{ admin_static.url(filename='admin/js/actions.js', v='1.0.0') }}"></script>
37
+ {% endif %}
38
+ {% endmacro %}
@@ -0,0 +1,115 @@
1
+ {% import 'admin/layout.html' as layout with context -%}
2
+ {% import 'admin/static.html' as admin_static with context %}
3
+ <!DOCTYPE html>
4
+ <html lang="en">
5
+ <head>
6
+ <title>{% block title %}{% if admin_view.category %}{{ admin_view.category }} - {% endif %}{{ admin_view.name }} - {{ admin_view.admin.name }}{% endblock %}</title>
7
+ {% block head_meta %}
8
+ <meta charset="UTF-8">
9
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
10
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
11
+ <meta name="description" content="">
12
+ <meta name="author" content="">
13
+ {% endblock %}
14
+ {% block head_css %}
15
+ <link href="https://cdn.jsdelivr.net/npm/@tabler/core@1.4.0/dist/css/tabler.min.css" rel="stylesheet" {{ admin_csp_nonce_attribute }}>
16
+ {% if admin_view.admin.theme.tabler_icons %}
17
+ <link href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@3.31.0/dist/tabler-icons.min.css" rel="stylesheet" {{ admin_csp_nonce_attribute }}>
18
+ {% endif %}
19
+ <link href="{{ url_for('flask_admin_tabler.static', filename='admin/css/tabler/admin.css') }}" rel="stylesheet" {{ admin_csp_nonce_attribute }}>
20
+ {% if admin_view.extra_css %}
21
+ {% for css_url in admin_view.extra_css %}
22
+ <link href="{{ css_url }}" rel="stylesheet" {{ admin_csp_nonce_attribute }}>
23
+ {% endfor %}
24
+ {% endif %}
25
+ {% endblock %}
26
+ {% block head %}
27
+ {% endblock %}
28
+ {% block head_tail %}
29
+ {% endblock %}
30
+ </head>
31
+ <body class="antialiased">
32
+ <div class="page">
33
+ {% block page_body %}
34
+ <!-- Sticky top navbar -->
35
+ <header class="navbar navbar-expand-md sticky-top d-print-none">
36
+ <div class="container-xl">
37
+ {% block brand %}
38
+ <a class="navbar-brand navbar-brand-autodark" href="{{ admin_view.admin.url }}">{{ admin_view.admin.name }}</a>
39
+ {% endblock %}
40
+ <!-- Toggle button for smaller screens -->
41
+ <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-menu"
42
+ aria-controls="navbar-menu" aria-expanded="false" aria-label="Toggle navigation">
43
+ <span class="navbar-toggler-icon"></span>
44
+ </button>
45
+ <!-- Collapsible menu -->
46
+ <div class="collapse navbar-collapse" id="navbar-menu">
47
+ {% block main_menu %}
48
+ <ul class="navbar-nav me-auto">
49
+ {{ layout.menu() }}
50
+ </ul>
51
+ {% endblock %}
52
+ {% block menu_links %}
53
+ <ul class="navbar-nav ms-auto">
54
+ {{ layout.menu_links() }}
55
+ </ul>
56
+ {% endblock %}
57
+ {% block access_control %}
58
+ {% endblock %}
59
+ </div>
60
+ </div>
61
+ </header>
62
+
63
+ <!-- Page wrapper -->
64
+ <div class="page-wrapper">
65
+ <!-- Page header -->
66
+ <div class="page-header d-print-none">
67
+ <div class="container-xl">
68
+ <div class="row g-2 align-items-center">
69
+ <div class="col">
70
+ {% block page_title %}
71
+ <h2 class="page-title">
72
+ {{ layout.menu_icon(admin_view.menu) }}
73
+ {{ admin_view.name }}
74
+ </h2>
75
+ {% endblock %}
76
+ </div>
77
+ </div>
78
+ </div>
79
+ </div>
80
+
81
+ <!-- Page body -->
82
+ <div class="page-body">
83
+ <div class="container-xl">
84
+ {% block messages %}
85
+ {{ layout.messages() }}
86
+ {% endblock %}
87
+
88
+ {# store the jinja2 context for form_rules rendering logic #}
89
+ {% set render_ctx = h.resolve_ctx() %}
90
+
91
+ {% block body %}{% endblock %}
92
+ </div>
93
+ </div>
94
+ </div>
95
+ {% endblock %}
96
+ </div>
97
+
98
+ {% block tail_js %}
99
+ <script {{ admin_csp_nonce_attribute }} src="{{ admin_static.url(filename='vendor/jquery.min.js', v='3.5.1') }}" type="text/javascript"></script>
100
+ <script {{ admin_csp_nonce_attribute }} src="https://cdn.jsdelivr.net/npm/@tabler/core@1.4.0/dist/js/tabler.min.js" type="text/javascript"></script>
101
+ <script {{ admin_csp_nonce_attribute }} src="{{ admin_static.url(filename='vendor/moment.min.js', v='2.9.4') }}" type="text/javascript"></script>
102
+ <script {{ admin_csp_nonce_attribute }} src="{{ admin_static.url(filename='vendor/select2/select2.min.js', v='4.2.1') }}"
103
+ type="text/javascript"></script>
104
+ <script {{ admin_csp_nonce_attribute }} src="{{ admin_static.url(filename='admin/js/helpers.js', v='1.0.0') }}" type="text/javascript"></script>
105
+ {% if admin_view.extra_js %}
106
+ {% for js_url in admin_view.extra_js %}
107
+ <script {{ admin_csp_nonce_attribute }} src="{{ js_url }}" type="text/javascript"></script>
108
+ {% endfor %}
109
+ {% endif %}
110
+ {% endblock %}
111
+
112
+ {% block tail %}
113
+ {% endblock %}
114
+ </body>
115
+ </html>
@@ -0,0 +1,9 @@
1
+ {% extends 'admin/master.html' %}
2
+ {% import 'admin/lib.html' as lib with context %}
3
+
4
+ {% block body %}
5
+ {% block header %}<h3>{{ header_text }}</h3>{% endblock %}
6
+ {% block fa_form %}
7
+ {{ lib.render_form(form, dir_url) }}
8
+ {% endblock %}
9
+ {% endblock %}
@@ -0,0 +1,195 @@
1
+ {% extends 'admin/master.html' %}
2
+ {% import 'admin/lib.html' as lib with context %}
3
+ {% import 'admin/actions.html' as actionslib with context %}
4
+
5
+ {% block body %}
6
+ {% block breadcrums %}
7
+ <nav aria-label="breadcrumb">
8
+ <ol class="breadcrumb">
9
+ <li class="breadcrumb-item">
10
+ <a href="{{ get_dir_url('.index_view', path=None) }}">{{ _gettext('Root') }}</a>
11
+ </li>
12
+ {% for name, path in breadcrumbs[:-1] %}
13
+ <li class="breadcrumb-item">
14
+ <a href="{{ get_dir_url('.index_view', path=path) }}">{{ name }}</a>
15
+ </li>
16
+ {% endfor %}
17
+ {% if breadcrumbs %}
18
+ <li class="breadcrumb-item">
19
+ <a href="{{ get_dir_url('.index_view', path=breadcrumbs[-1][1]) }}">{{ breadcrumbs[-1][0] }}</a>
20
+ </li>
21
+ {% endif %}
22
+ </ol>
23
+ </nav>
24
+ {% endblock %}
25
+
26
+ {% block file_list_table %}
27
+ <div class="table-responsive">
28
+ <table class="table table-vcenter table-striped table-bordered model-list">
29
+ <thead>
30
+ <tr>
31
+ {% block list_header scoped %}
32
+ {% if actions %}
33
+ <th class="list-checkbox-column">
34
+ <input type="checkbox" name="rowtoggle" class="action-rowtoggle" />
35
+ </th>
36
+ {% endif %}
37
+ <th class="">&nbsp;</th>
38
+ {% for column in admin_view.column_list %}
39
+ <th>
40
+ {% if admin_view.is_column_sortable(column) %}
41
+ {% if sort_column == column %}
42
+ <a href="{{ sort_url(column, dir_path, True) }}" title="{{ _gettext('Sort by %(name)s', name=column) }}">
43
+ {{ admin_view.column_label(column) }}
44
+ {% if sort_desc %}
45
+ <span class="fa fa-chevron-up"></span>
46
+ {% else %}
47
+ <span class="fa fa-chevron-down"></span>
48
+ {% endif %}
49
+ </a>
50
+ {% else %}
51
+ <a href="{{ sort_url(column, dir_path) }}" title="{{ _gettext('Sort by %(name)s', name=column) }}">{{ admin_view.column_label(column) }}</a>
52
+ {% endif %}
53
+ {% else %}
54
+ {{ _gettext(admin_view.column_label(column)) }}
55
+ {% endif %}
56
+ </th>
57
+ {% endfor %}
58
+ {% endblock %}
59
+ </tr>
60
+ </thead>
61
+ {% for name, path, is_dir, size, date in items %}
62
+ <tr>
63
+ {% block list_row scoped %}
64
+ {% if actions %}
65
+ <td>
66
+ {% if not is_dir %}
67
+ <input type="checkbox" name="rowid" class="action-checkbox" value="{{ path }}" />
68
+ {% endif %}
69
+ </td>
70
+ {% endif %}
71
+ <td>
72
+ {% block list_row_actions scoped %}
73
+ {% if admin_view.can_rename and path and name != '..' %}
74
+ {%- if admin_view.rename_modal -%}
75
+ {{ lib.add_modal_button(url=get_url('.rename', path=path, modal=True),
76
+ title=_gettext('Rename File'),
77
+ content='<i class="fa fa-pencil"></i>') }}
78
+ {% else %}
79
+ <a class="icon" href="{{ get_url('.rename', path=path) }}" title="{{ _gettext('Rename File') }}">
80
+ <i class="fa fa-pencil"></i>
81
+ </a>
82
+ {%- endif -%}
83
+ {% endif %}
84
+ {%- if admin_view.can_delete and path -%}
85
+ {% if is_dir %}
86
+ {% if name != '..' and admin_view.can_delete_dirs %}
87
+ <form class="icon" method="POST" action="{{ get_url('.delete') }}">
88
+ {{ delete_form.path(value=path) }}
89
+ {% if delete_form.csrf_token is defined and delete_form.csrf_token %}
90
+ {{ delete_form.csrf_token }}
91
+ {% endif %}
92
+ <button onclick="return confirm('{{ _gettext('Are you sure you want to delete \\\'%(name)s\\\' recursively?', name=name) }}')">
93
+ <i class="fa fa-times"></i>
94
+ </button>
95
+ </form>
96
+ {% endif %}
97
+ {% else %}
98
+ <form class="icon" method="POST" action="{{ get_url('.delete') }}">
99
+ {{ delete_form.path(value=path) }}
100
+ {% if delete_form.csrf_token is defined and delete_form.csrf_token %}
101
+ {{ delete_form.csrf_token }}
102
+ {% endif %}
103
+ <button onclick="return confirm('{{ _gettext('Are you sure you want to delete \\\'%(name)s\\\'?', name=name) }}')">
104
+ <i class="fa fa-trash"></i>
105
+ </button>
106
+ </form>
107
+ {% endif %}
108
+ {%- endif -%}
109
+ {% endblock %}
110
+ </td>
111
+ {% if is_dir %}
112
+ <td colspan="2">
113
+ <a href="{{ get_dir_url('.index_view', path)|safe }}">
114
+ <i class="fa fa-folder-o"></i> <span>{{ name }}</span>
115
+ </a>
116
+ </td>
117
+ {% else %}
118
+ <td>
119
+ {% if admin_view.can_download %}
120
+ {%- if admin_view.edit_modal and admin_view.is_file_editable(path) -%}
121
+ {{ lib.add_modal_button(url=get_file_url(path, modal=True)|safe,
122
+ btn_class='', content=name) }}
123
+ {% else %}
124
+ <a href="{{ get_file_url(path)|safe }}">{{ name }}</a>
125
+ {%- endif -%}
126
+ {% else %}
127
+ {{ name }}
128
+ {% endif %}
129
+ </td>
130
+ {% if admin_view.is_column_visible('size') %}
131
+ <td>
132
+ {{ size|filesizeformat }}
133
+ </td>
134
+ {% endif %}
135
+ {% endif %}
136
+ {% if admin_view.is_column_visible('date') %}
137
+ <td>
138
+ {{ timestamp_format(date) }}
139
+ </td>
140
+ {% endif %}
141
+ {% endblock %}
142
+ </tr>
143
+ {% endfor %}
144
+ </table>
145
+ </div>
146
+ {% endblock %}
147
+ {% block toolbar %}
148
+ <div class="btn-toolbar">
149
+ {% if admin_view.can_upload %}
150
+ <div class="btn-group">
151
+ {%- if admin_view.upload_modal -%}
152
+ {{ lib.add_modal_button(url=get_dir_url('.upload', path=dir_path, modal=True),
153
+ btn_class="btn btn-secondary",
154
+ content=_gettext('Upload File')) }}
155
+ {% else %}
156
+ <a class="btn btn-secondary" href="{{ get_dir_url('.upload', path=dir_path) }}">{{ _gettext('Upload File') }}</a>
157
+ {%- endif -%}
158
+ </div>
159
+ {% endif %}
160
+ {% if admin_view.can_mkdir %}
161
+ <div class="ms-1">
162
+ {%- if admin_view.mkdir_modal -%}
163
+ {{ lib.add_modal_button(url=get_dir_url('.mkdir', path=dir_path, modal=True),
164
+ btn_class="btn btn-secondary",
165
+ content=_gettext('Create Directory')) }}
166
+ {% else %}
167
+ <a class="btn btn-secondary" href="{{ get_dir_url('.mkdir', path=dir_path) }}">{{ _gettext('Create Directory') }}</a>
168
+ {%- endif -%}
169
+ </div>
170
+ {% endif %}
171
+ {% if actions %}
172
+ <div class="ms-1">
173
+ {{ actionslib.dropdown(actions, 'dropdown-toggle btn btn-secondary') }}
174
+ </div>
175
+ {% endif %}
176
+ </div>
177
+ {% endblock %}
178
+
179
+ {% block actions %}
180
+ {{ actionslib.form(actions, get_url('.action_view')) }}
181
+ {% endblock %}
182
+
183
+ {%- if admin_view.rename_modal or admin_view.mkdir_modal
184
+ or admin_view.upload_modal or admin_view.edit_modal -%}
185
+ {{ lib.add_modal_window() }}
186
+ {%- endif -%}
187
+ {% endblock %}
188
+
189
+ {% block tail %}
190
+ {{ super() }}
191
+ {{ actionslib.script(_gettext('Please select at least one file.'),
192
+ actions,
193
+ actions_confirmation) }}
194
+ <script {{ admin_csp_nonce_attribute }} src="{{ admin_static.url(filename='admin/js/bs4_modal.js', v='1.0.0') }}"></script>
195
+ {% endblock %}