mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
* Remove dark mode styling * Condense & rename light mode stylesheet * Upgrade to Bootstrap 5.3.2 * Swap out Bootstrap for Tabler; remove custom styling * Update base page layout for Tabler * Update login page * Bump node to v18 * Update button styles * Update object list view * Tweak navbar size * Clean up dashboard widgets * Ditch separate stylesheet for print media * Remove simplebar * Remove obsolete sidebar styling * Clean up object view template * Clean up object edit template * Standardize primary button sizing * Clean up object list styling * Add buttons for add & import to navigation menu * Fix global search bar * Fix slim-select form widget styling * Fix toast styling * Set base fonts * Clean up paginator styling * Clean up navigation menu group headings * Clean up footer links * Clean up card styles * Move SVG styles to a designated directory * Restructure SCSS files * Remove obsolete/redundant dependencies * Fix icon spacing * Update background color classes * Tweak banner & footer styling and spacing * Fix badge background colors in table content * Bump @types/bootstrap to 5.2.10 * Clean up form layouts * Fix object selector button style * Fix icon padding inside small buttons * Fix icon & badge spacing inside buttons and tabs * Hide paginator for empty pages * Fix hover color for list items (Tabler bug #1694) * Fix width of checkbox column in empty tables * Clean up bulk edit template * Fix border color of reslug button * Package & serve Google fonts locally * Fix tab styling * Reduce vetical space at top of dashboard * Remove obsolete content-wrapper template block * Fix icon spacing in dropdown menu items * Fix color label sizing * Separate bulk delete form & object list into tabs * Fix styling of filter group headings * Fix styling for object changelog & journal views * Standardize ordering & styling of action buttons * Fix designation of active menu item * Automatically expand menu section containing the active link * Clean up nav menu styling * Remove button colors; hide buttons except on hover/active * Highlight menu group containing the active item * Update & standardize alert styling * Refactor base templates to ensure consistent display of header content * Tweak styling for links inside badges * Clean up top menu * Fix JSON/YAML toggles for config context data * Fix object template header * Constrain tabs to container-xl; tweak header margins * Fix object identifier styling * Fix positioning of card header buttons * Remove padding from HTMX tables inside cards * Ensure consistent use of row headings in attribute tables * Remove padding surrounding tables inside cards * Remove obsolete CSS classes * Misc cleanup of old styling * Refactor 'controls' template block; ditch old classes * Fix login button sizing * Limit object edit form width * Append asterisk to required form field labels * Remove obsolete styling * Remove obsolete styling * Fix position of progress bar outside label * Fix alignment of delete button in report/script lists * Fix <pre> styling * Clean up page headers * Replace SVG icons with Material Design icons * Restore dark mode togle functionality * Fix top navbar background color under dark mode * Rebuild static assets
This commit is contained in:
15
netbox/templates/inc/alerts/danger.html
Normal file
15
netbox/templates/inc/alerts/danger.html
Normal file
@@ -0,0 +1,15 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div class="alert alert-danger bg-danger-subtle mx-3 my-2" role="alert">
|
||||
<div class="d-flex">
|
||||
<div>
|
||||
<i class="mdi mdi-alert-octagon p-2"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="alert-title">{% block title %}{% trans title %}{% endblock %}</h4>
|
||||
{% block content %}
|
||||
<div class="text-secondary">{% trans message %}</div>
|
||||
{% endblock content %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
15
netbox/templates/inc/alerts/info.html
Normal file
15
netbox/templates/inc/alerts/info.html
Normal file
@@ -0,0 +1,15 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div class="alert alert-info bg-info-subtle mx-3 my-2" role="alert">
|
||||
<div class="d-flex">
|
||||
<div>
|
||||
<i class="mdi mdi-information-outline p-2"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="alert-title">{% block title %}{% trans title %}{% endblock %}</h4>
|
||||
{% block content %}
|
||||
<div class="text-secondary">{% trans message %}</div>
|
||||
{% endblock content %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
15
netbox/templates/inc/alerts/success.html
Normal file
15
netbox/templates/inc/alerts/success.html
Normal file
@@ -0,0 +1,15 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div class="alert alert-success bg-success-subtle mx-3 my-2" role="alert">
|
||||
<div class="d-flex">
|
||||
<div>
|
||||
<i class="mdi mdi-check-bold p-2"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="alert-title">{% block title %}{% trans title %}{% endblock %}</h4>
|
||||
{% block content %}
|
||||
<div class="text-secondary">{% trans message %}</div>
|
||||
{% endblock content %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
15
netbox/templates/inc/alerts/warning.html
Normal file
15
netbox/templates/inc/alerts/warning.html
Normal file
@@ -0,0 +1,15 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div class="alert alert-warning bg-warning-subtle mx-3 my-2" role="alert">
|
||||
<div class="d-flex">
|
||||
<div>
|
||||
<i class="mdi mdi-alert p-2"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="alert-title">{% block title %}{% trans title %}{% endblock %}</h4>
|
||||
{% block content %}
|
||||
<div class="text-secondary">{% trans message %}</div>
|
||||
{% endblock content %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
4
netbox/templates/inc/banner.html
Normal file
4
netbox/templates/inc/banner.html
Normal file
@@ -0,0 +1,4 @@
|
||||
{# Display top or bottom banner content #}
|
||||
<div class="text-center mx-3 m-2">
|
||||
{{ content|safe }}
|
||||
</div>
|
@@ -12,7 +12,9 @@
|
||||
{% for heading, fields in filter_form.fieldsets %}
|
||||
<div class="col col-12">
|
||||
{% if heading %}
|
||||
<h6>{{ heading }}</h6>
|
||||
<div class="hr-text">
|
||||
<span>{{ heading }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for name in fields %}
|
||||
{% with field=filter_form|get_item:name %}
|
||||
@@ -20,9 +22,6 @@
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if not forloop.last %}
|
||||
<hr class="card-divider mt-0" />
|
||||
{% endif %}
|
||||
{% empty %}
|
||||
{# List all non-customfield filters as declared in the form class #}
|
||||
{% for field in filter_form.visible_fields %}
|
||||
@@ -35,21 +34,23 @@
|
||||
{% endfor %}
|
||||
{% if filter_form.custom_fields %}
|
||||
{# List all custom field filters #}
|
||||
<hr class="card-divider mt-0" />
|
||||
{% for name in filter_form.custom_fields %}
|
||||
<div class="col col-12">
|
||||
<div class="col col-12">
|
||||
<div class="hr-text">
|
||||
<span>{% trans "Custom Fields" %}</span>
|
||||
</div>
|
||||
{% for name in filter_form.custom_fields %}
|
||||
{% with field=filter_form|get_item:name %}
|
||||
{% render_field field %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-footer text-end noprint border-0">
|
||||
<button type="button" class="btn btn-sm btn-outline-danger m-1" data-reset-select>
|
||||
<div class="card-footer text-end d-print-none border-0">
|
||||
<button type="button" class="btn btn-outline-danger m-1" data-reset-select>
|
||||
<i class="mdi mdi-backspace"></i> {% trans "Reset" %}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary m-1">
|
||||
<button type="submit" class="btn btn-primary m-1">
|
||||
<i class="mdi mdi-magnify"></i> {% trans "Search" %}
|
||||
</button>
|
||||
</div>
|
||||
|
@@ -1,39 +1,17 @@
|
||||
{% load helpers %}
|
||||
|
||||
<div id="django-messages" class="toast-container">
|
||||
<div id="django-messages" class="toast-container position-fixed bottom-0 end-0 p-3">
|
||||
|
||||
{# Non-Field Form Errors #}
|
||||
{% if form and form.non_field_errors %}
|
||||
{% for error in form.non_field_errors.get_json_data %}
|
||||
<div class="django-message toast align-items-center border-0 bg-danger" data-django-type="non-field-error" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="10000">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
<i class="mdi mdi-{{ "danger"|icon_from_status }} me-1"></i>
|
||||
{{ error.message }}
|
||||
</div>
|
||||
<button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'inc/toast.html' with status="danger" title="Error" message=error.message %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{# Django Messages #}
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
{% with message.level_tag|status_from_tag as status %}
|
||||
{% with status|icon_from_status as icon %}
|
||||
<div class="django-message toast align-items-center border-0 bg-{{ status }}" data-django-type="message" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="10000">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
<i class="mdi mdi-{{ icon }} me-1"></i>
|
||||
{{ message }}
|
||||
</div>
|
||||
<button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% for message in messages %}
|
||||
{% include 'inc/toast.html' with status=message.level_tag|status_from_tag %}
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
|
@@ -1,12 +1,16 @@
|
||||
{% load buttons %}
|
||||
{% load i18n %}
|
||||
|
||||
<div class="alert alert-warning text-end" role="alert">
|
||||
<div class="float-start">
|
||||
<i class="mdi mdi-alert"></i>
|
||||
{% blocktrans trimmed with model=model|meta:"verbose_name" prerequisite_model=prerequisite_model|meta:"verbose_name" %}
|
||||
Before you can add a {{ model }} you must first create a <strong>{{ prerequisite_model }}</strong>.
|
||||
{% endblocktrans %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>
|
||||
<i class="mdi mdi-alert p-2"></i>
|
||||
{% blocktrans trimmed with model=model|meta:"verbose_name" prerequisite_model=prerequisite_model|meta:"verbose_name" %}
|
||||
Before you can add a {{ model }} you must first create a <strong>{{ prerequisite_model }}</strong>.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
<div>
|
||||
{% add_button prerequisite_model %}
|
||||
</div>
|
||||
</div>
|
||||
{% add_button prerequisite_model %}
|
||||
</div>
|
||||
|
@@ -1,55 +1,117 @@
|
||||
{% load helpers %}
|
||||
{% load i18n %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col col-md-6 mb-0">
|
||||
{# Page number carousel #}
|
||||
{% if page %}
|
||||
<div class="d-flex justify-content-between align-items-center border-top p-2">
|
||||
|
||||
{# Pages carousel #}
|
||||
{% if paginator.num_pages > 1 %}
|
||||
<div class="btn-group btn-group-sm mb-3" role="group" aria-label="Pages">
|
||||
{% if page.has_previous %}
|
||||
<a href="{% querystring request page=page.previous_page_number %}" class="btn btn-outline-secondary">
|
||||
<i class="mdi mdi-chevron-double-left"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% for p in page.smart_pages %}
|
||||
{% if p %}
|
||||
<a href="{% querystring request page=p %}" class="btn btn-outline-secondary{% if page.number == p %} active{% endif %}">
|
||||
{{ p }}
|
||||
</a>
|
||||
{% else %}
|
||||
<button type="button" class="btn btn-outline-secondary" disabled>
|
||||
<span>…</span>
|
||||
</button>
|
||||
<nav aria-label="{% trans "Page selection" %}">
|
||||
<ul class="pagination mb-0">
|
||||
|
||||
{# Previous page #}
|
||||
{% if page.has_previous %}
|
||||
<li class="page-item">
|
||||
{% if htmx %}
|
||||
<a href="#"
|
||||
hx-get="{{ table.htmx_url }}{% querystring request page=page.previous_page_number %}"
|
||||
hx-target="closest .htmx-container"
|
||||
{% if not table.embedded %}hx-push-url="true"{% endif %}
|
||||
class="page-link"
|
||||
>
|
||||
<i class="mdi mdi-chevron-left"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{% querystring request page=page.previous_page_number %}" class="page-link">
|
||||
<i class="mdi mdi-chevron-left"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if page.has_next %}
|
||||
<a href="{% querystring request page=page.next_page_number %}" class="btn btn-outline-secondary">
|
||||
<i class="mdi mdi-chevron-double-right"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col col-md-6 mb-0 text-end">
|
||||
{# Per-page count selector #}
|
||||
{% if page %}
|
||||
<div class="dropdown dropup">
|
||||
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
||||
{% trans "Per Page" %}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% for n in page.paginator.get_page_lengths %}
|
||||
<li>
|
||||
<a href="{% querystring request per_page=n %}" class="dropdown-item">{{ n }}</a>
|
||||
{# /Previous page #}
|
||||
|
||||
{# Page numbers #}
|
||||
{% for p in page.smart_pages %}
|
||||
<li class="page-item{% if page.number == p %} active" aria-current="page{% endif %}">
|
||||
{% if p and htmx %}
|
||||
<a href="#"
|
||||
hx-get="{{ table.htmx_url }}{% querystring request page=p %}"
|
||||
hx-target="closest .htmx-container"
|
||||
{% if not table.embedded %}hx-push-url="true"{% endif %}
|
||||
class="page-link"
|
||||
>
|
||||
{{ p }}
|
||||
</a>
|
||||
{% elif p %}
|
||||
<a href="{% querystring request page=p %}" class="btn btn-outline-secondary{% if page.number == p %} active{% endif %}">
|
||||
{{ p }}
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="page-link" disabled>…</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{# /Page numbers #}
|
||||
|
||||
{# Next page #}
|
||||
{% if page.has_next %}
|
||||
<li class="page-item">
|
||||
{% if htmx %}
|
||||
<a href="#"
|
||||
hx-get="{{ table.htmx_url }}{% querystring request page=page.next_page_number %}"
|
||||
hx-target="closest .htmx-container"
|
||||
{% if not table.embedded %}hx-push-url="true"{% endif %}
|
||||
class="page-link"
|
||||
>
|
||||
<i class="mdi mdi-chevron-right"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{% querystring request page=page.next_page_number %}" class="page-link">
|
||||
<i class="mdi mdi-chevron-right"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{# /Next page #}
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<small class="text-end text-muted">
|
||||
{% blocktrans trimmed with start=page.start_index end=page.end_index total=page.paginator.count %}
|
||||
Showing {{ start }}-{{ end }} of {{ total }}
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{# /Pages carousel #}
|
||||
|
||||
{# Showing #}
|
||||
<small class="text-end text-muted">
|
||||
{% blocktrans trimmed with start=page.start_index end=page.end_index total=page.paginator.count %}
|
||||
Showing {{ start }}-{{ end }} of {{ total }}
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
{# /Showing #}
|
||||
|
||||
{# Pagination options #}
|
||||
<nav class="text-end" aria-label="{% trans "Pagination options" %}">
|
||||
{% if page %}
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
||||
{% trans "Per Page" %}
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
{% for n in page.paginator.get_page_lengths %}
|
||||
{% if htmx %}
|
||||
<a href="#"
|
||||
hx-get="{{ table.htmx_url }}{% querystring request per_page=n %}"
|
||||
hx-target="closest .htmx-container"
|
||||
{% if not table.embedded %}hx-push-url="true"{% endif %}
|
||||
class="dropdown-item"
|
||||
>{{ n }}</a>
|
||||
{% else %}
|
||||
<a href="{% querystring request per_page=n %}" class="dropdown-item">{{ n }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</nav>
|
||||
{# /Pagination options #}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@@ -1,75 +0,0 @@
|
||||
{% load helpers %}
|
||||
{% load i18n %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col col-md-6 mb-0">
|
||||
{# Page number carousel #}
|
||||
{% if paginator.num_pages > 1 %}
|
||||
<div class="btn-group btn-group-sm" role="group" aria-label="Pages">
|
||||
{% if page.has_previous %}
|
||||
<a href="#"
|
||||
hx-get="{{ table.htmx_url }}{% querystring request page=page.previous_page_number %}"
|
||||
hx-target="closest .htmx-container"
|
||||
{% if not table.embedded %}hx-push-url="true"{% endif %}
|
||||
class="btn btn-outline-secondary"
|
||||
>
|
||||
<i class="mdi mdi-chevron-double-left"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% for p in page.smart_pages %}
|
||||
{% if p %}
|
||||
<a href="#"
|
||||
hx-get="{{ table.htmx_url }}{% querystring request page=p %}"
|
||||
hx-target="closest .htmx-container"
|
||||
{% if not table.embedded %}hx-push-url="true"{% endif %}
|
||||
class="btn btn-outline-secondary{% if page.number == p %} active{% endif %}"
|
||||
>
|
||||
{{ p }}
|
||||
</a>
|
||||
{% else %}
|
||||
<button type="button" class="btn btn-outline-secondary" disabled>
|
||||
<span>…</span>
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if page.has_next %}
|
||||
<a href="#"
|
||||
hx-get="{{ table.htmx_url }}{% querystring request page=page.next_page_number %}"
|
||||
hx-target="closest .htmx-container"
|
||||
{% if not table.embedded %}hx-push-url="true"{% endif %}
|
||||
class="btn btn-outline-secondary"
|
||||
>
|
||||
<i class="mdi mdi-chevron-double-right"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col col-md-6 mb-0 text-end">
|
||||
{# Per-page count selector #}
|
||||
{% if page %}
|
||||
<div class="dropdown dropup">
|
||||
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
||||
{% trans "Per Page" %}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% for n in page.paginator.get_page_lengths %}
|
||||
<li>
|
||||
<a href="#"
|
||||
hx-get="{{ table.htmx_url }}{% querystring request per_page=n %}"
|
||||
hx-target="closest .htmx-container"
|
||||
{% if not table.embedded %}hx-push-url="true"{% endif %}
|
||||
class="dropdown-item"
|
||||
>{{ n }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<small class="text-end text-muted">
|
||||
{% blocktrans trimmed with start=page.start_index end=page.end_index total=page.paginator.count %}
|
||||
Showing {{ start }}-{{ end }} of {{ total }}
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
@@ -5,7 +5,7 @@
|
||||
{% if heading %}
|
||||
<h5 class="card-header{% if panel_class %} text-{{ panel_class }}{% endif %}">{{ heading }}</h5>
|
||||
{% endif %}
|
||||
<div class="card-body table-responsive">
|
||||
<div class="table-responsive">
|
||||
{% if table.rows %}
|
||||
{% render_table table 'inc/table.html' %}
|
||||
{% else %}
|
||||
|
@@ -5,32 +5,30 @@
|
||||
{% if custom_fields %}
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "Custom Fields" %}</h5>
|
||||
<div class="card-body">
|
||||
{% for group_name, fields in custom_fields.items %}
|
||||
{% if group_name %}
|
||||
<h6>{{ group_name }}</h6>
|
||||
{% endif %}
|
||||
<table class="table table-hover attr-table">
|
||||
{% for field, value in fields.items %}
|
||||
<tr>
|
||||
<th scope="row">{{ field }}
|
||||
{% if field.description %}
|
||||
<i
|
||||
class="mdi mdi-information text-primary"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="right"
|
||||
title="{{ field.description|escape }}"
|
||||
></i>
|
||||
{% endif %}
|
||||
</th>
|
||||
<td>
|
||||
{% customfield_value field value %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% for group_name, fields in custom_fields.items %}
|
||||
{% if group_name %}
|
||||
<h6>{{ group_name }}</h6>
|
||||
{% endif %}
|
||||
<table class="table table-hover attr-table">
|
||||
{% for field, value in fields.items %}
|
||||
<tr>
|
||||
<th scope="row">{{ field }}
|
||||
{% if field.description %}
|
||||
<i
|
||||
class="mdi mdi-information text-primary"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="right"
|
||||
title="{{ field.description|escape }}"
|
||||
></i>
|
||||
{% endif %}
|
||||
</th>
|
||||
<td>
|
||||
{% customfield_value field value %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
@@ -5,8 +5,8 @@
|
||||
<h5 class="card-header">{% trans "Images" %}</h5>
|
||||
{% htmx_table 'extras:imageattachment_list' content_type_id=object|content_type_id object_id=object.pk %}
|
||||
{% if perms.extras.add_imageattachment %}
|
||||
<div class="card-footer text-end noprint">
|
||||
<a href="{% url 'extras:imageattachment_add' %}?content_type={{ object|content_type_id }}&object_id={{ object.pk }}" class="btn btn-primary btn-sm">
|
||||
<div class="card-footer text-end d-print-none">
|
||||
<a href="{% url 'extras:imageattachment_add' %}?content_type={{ object|content_type_id }}&object_id={{ object.pk }}" class="btn btn-primary">
|
||||
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> {% trans "Attach an image" %}
|
||||
</a>
|
||||
</div>
|
||||
|
@@ -10,9 +10,9 @@
|
||||
{{ qs.model|meta:"verbose_name_plural"|bettertitle }}
|
||||
{% with count=qs.count %}
|
||||
{% if count %}
|
||||
<span class="badge bg-primary rounded-pill">{{ count }}</span>
|
||||
<span class="badge text-bg-primary rounded-pill">{{ count }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-light rounded-pill">—</span>
|
||||
<span class="badge text-bg-light rounded-pill">—</span>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</a>
|
||||
|
@@ -1,67 +0,0 @@
|
||||
{% load i18n %}
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="dropdown profile-button">
|
||||
<button type="button" aria-expanded="false" data-bs-toggle="dropdown" class="btn btn-outline-secondary dropdown-toggle w-100">
|
||||
<i class="mdi mdi-account"></i>
|
||||
<span id="navbar_user">{{ request.user|truncatechars:"30" }}</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li>
|
||||
<button type="button" class="dropdown-item color-mode-toggle">
|
||||
<i class="color-mode-icon mdi mdi-lightbulb"></i>
|
||||
<span class="color-mode-text">{% trans "Dark Mode" %}</span>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
{% if request.user.is_staff %}
|
||||
<a class="dropdown-item" href="{% url 'admin:index' %}">
|
||||
<i class="mdi mdi-cog"></i> {% trans "Admin" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'account:profile' %}">
|
||||
<i class="mdi mdi-account"></i> {% trans "Profile" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'account:bookmarks' %}">
|
||||
<i class="mdi mdi-bookmark"></i> {% trans "Bookmarks" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'account:preferences' %}">
|
||||
<i class="mdi mdi-wrench"></i> {% trans "Preferences" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'account:usertoken_list' %}">
|
||||
<i class="mdi mdi-key"></i> {% trans "API Tokens" %}
|
||||
</a>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider" /></li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'logout' %}">
|
||||
<i class="mdi mdi-logout-variant"></i> {% trans "Log Out" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-primary ws-nowrap" type="button" href="{% url 'login' %}?next={{ request.path }}">
|
||||
<i class="mdi mdi-login-variant"></i> {% trans "Log In" %}
|
||||
</a>
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown">
|
||||
<span class="visually-hidden">{% trans "Toggle Dropdown" %}</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li>
|
||||
<button class="dropdown-item color-mode-toggle">
|
||||
<i class="color-mode-icon mdi mdi-lightbulb"></i>
|
||||
<span class="color-mode-text">{% trans "Dark Mode" %}</span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
@@ -1,6 +0,0 @@
|
||||
<form class="input-group" action="{% url 'search' %}" method="get">
|
||||
<input name="q" type="text" aria-label="Search" placeholder="Search" class="form-control" />
|
||||
<button class="btn btn-primary" type="submit">
|
||||
<i class="mdi mdi-magnify"></i>
|
||||
</button>
|
||||
</form>
|
@@ -4,11 +4,16 @@
|
||||
|
||||
{% if object.data_file and object.data_file.last_updated > object.data_synced %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<i class="mdi mdi-alert"></i> {% trans "Data is out of sync with upstream file" %} (<a href="{{ object.data_file.get_absolute_url }}">{{ object.data_file }}</a>).
|
||||
{% if request.user|can_sync:object %}
|
||||
<div class="float-end">
|
||||
{% sync_button object %}
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>
|
||||
<i class="mdi mdi-alert"></i>
|
||||
{% trans "Data is out of sync with upstream file" %} (<a href="{{ object.data_file.get_absolute_url }}">{{ object.data_file }}</a>).
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if request.user|can_sync:object %}
|
||||
<div>
|
||||
{% sync_button object %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@@ -2,19 +2,19 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-auto table-controls noprint">
|
||||
<div class="input-group input-group-sm me-2 quicksearch hide-last-child">
|
||||
<div class="col-auto d-print-none">
|
||||
<div class="input-group me-2 quicksearch hide-last-child">
|
||||
<input type="search" results="5" name="q" id="quicksearch" class="form-control" placeholder="Quick search"
|
||||
hx-get="{{ request.full_path }}" hx-target="#object_list" hx-trigger="keyup changed delay:500ms, search" />
|
||||
<button class="btn bg-transparent" type="button" id="quicksearch_clear"><i class="mdi mdi-close-circle"></i></button>
|
||||
</div>
|
||||
{% block extra_table_controls %}{% endblock %}
|
||||
</div>
|
||||
<div class="col-auto ms-auto table-controls noprint">
|
||||
<div class="col-auto ms-auto d-print-none">
|
||||
{% if request.user.is_authenticated and table_modal %}
|
||||
<div class="table-configure input-group input-group-sm">
|
||||
<div class="table-configure input-group">
|
||||
<button type="button" data-bs-toggle="modal" title="{% trans "Configure Table" %}" data-bs-target="#{{ table_modal }}"
|
||||
class="btn btn-sm btn-outline-dark">
|
||||
class="btn">
|
||||
<i class="mdi mdi-cog"></i> {% trans "Configure Table" %}
|
||||
</button>
|
||||
</div>
|
||||
|
12
netbox/templates/inc/toast.html
Normal file
12
netbox/templates/inc/toast.html
Normal file
@@ -0,0 +1,12 @@
|
||||
{% load helpers %}
|
||||
|
||||
<div class="toast shadow-sm" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="10000">
|
||||
<div class="toast-header text-bg-{{ status }}">
|
||||
<i class="mdi mdi-{{ status|icon_from_status }} me-1"></i>
|
||||
{{ title }}
|
||||
<button type="button" class="btn-close me-0 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
{{ message }}
|
||||
</div>
|
||||
</div>
|
41
netbox/templates/inc/user_menu.html
Normal file
41
netbox/templates/inc/user_menu.html
Normal file
@@ -0,0 +1,41 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="nav-item dropdown">
|
||||
<a href="#" class="nav-link d-flex lh-1 text-reset p-0" data-bs-toggle="dropdown" aria-label="Open user menu">
|
||||
<div class="d-xl-block ps-2">
|
||||
<div>{{ request.user }}</div>
|
||||
<div class="mt-1 small text-secondary">{% if request.user.is_staff %}Staff{% else %}User{% endif %}</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
|
||||
{% if request.user.is_staff %}
|
||||
<a class="dropdown-item" href="{% url 'admin:index' %}">
|
||||
<i class="mdi mdi-cog"></i> {% trans "Admin" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{% url 'account:profile' %}" class="dropdown-item">
|
||||
<i class="mdi mdi-account"></i> {% trans "Profile" %}
|
||||
</a>
|
||||
<a href="{% url 'account:bookmarks' %}" class="dropdown-item">
|
||||
<i class="mdi mdi-bookmark"></i> {% trans "Bookmarks" %}
|
||||
</a>
|
||||
<a href="{% url 'account:preferences' %}" class="dropdown-item">
|
||||
<i class="mdi mdi-wrench"></i> {% trans "Preferences" %}
|
||||
</a>
|
||||
<a href="{% url 'account:usertoken_list' %}" class="dropdown-item">
|
||||
<i class="mdi mdi-key"></i> {% trans "API Tokens" %}
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="{% url 'logout' %}" class="dropdown-item">
|
||||
<i class="mdi mdi-logout-variant"></i> {% trans "Log Out" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-primary" type="button" href="{% url 'login' %}?next={{ request.path }}">
|
||||
<i class="mdi mdi-login-variant"></i> {% trans "Log In" %}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
Reference in New Issue
Block a user