improve styles and documentation

This commit is contained in:
checktheroads 2021-04-26 00:31:51 -07:00
parent bb55df34d7
commit aef513f038
27 changed files with 215 additions and 67 deletions

View File

@ -1,25 +1,38 @@
/**
* ParcelJS Bundle Configuration.
*
* @see https://parceljs.org/api.html
*/
const Bundler = require('parcel-bundler'); const Bundler = require('parcel-bundler');
// Bundler options common to all bundle jobs.
const options = { const options = {
logLevel: 2,
cache: true,
watch: false, watch: false,
minify: true, minify: true,
outDir: './dist', outDir: './dist',
publicUrl: '/static', publicUrl: '/static',
logLevel: 2,
cache: true,
}; };
// Get CLI arguments for optional overrides.
const args = process.argv.slice(2); const args = process.argv.slice(2);
// Allow cache disabling.
if (args.includes('--no-cache')) { if (args.includes('--no-cache')) {
options.cache = false; options.cache = false;
} }
// Style (SCSS) bundle jobs. Generally, everything should be bundled into netbox.css from main.scss
// unless there is a specific reason to do otherwise.
const styles = [ const styles = [
['main.scss', 'netbox.css'], ['main.scss', 'netbox.css'],
['rack_elevation.scss', 'rack_elevation.css'], ['rack_elevation.scss', 'rack_elevation.css'],
]; ];
// Script (JavaScript) bundle jobs. Generally, everything should be bundled into netbox.js from
// index.ts unless there is a specific reason to do otherwise.
const scripts = [ const scripts = [
['src/index.ts', 'netbox.js'], ['src/index.ts', 'netbox.js'],
['src/jobs.ts', 'jobs.js'], ['src/jobs.ts', 'jobs.js'],
@ -28,6 +41,9 @@ const scripts = [
['src/device/status.ts', 'status.js'], ['src/device/status.ts', 'status.js'],
]; ];
/**
* Run style bundle jobs.
*/
async function bundleStyles() { async function bundleStyles() {
for (const [input, outFile] of styles) { for (const [input, outFile] of styles) {
const instance = new Bundler(input, { outFile, ...options }); const instance = new Bundler(input, { outFile, ...options });
@ -35,6 +51,9 @@ async function bundleStyles() {
} }
} }
/**
* Run script bundle jobs.
*/
async function bundleScripts() { async function bundleScripts() {
for (const [input, outFile] of scripts) { for (const [input, outFile] of scripts) {
const instance = new Bundler(input, { outFile, ...options }); const instance = new Bundler(input, { outFile, ...options });
@ -42,10 +61,15 @@ async function bundleScripts() {
} }
} }
/**
* Run all bundle jobs.
*/
async function bundleAll() { async function bundleAll() {
if (args.includes('--styles')) { if (args.includes('--styles')) {
// Only run style jobs.
return await bundleStyles(); return await bundleStyles();
} else if (args.includes('--scripts')) { } else if (args.includes('--scripts')) {
// Only run script jobs.
return await bundleScripts(); return await bundleScripts();
} }
await bundleStyles(); await bundleStyles();

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,72 @@
// Dark Mode Styles for Flatpickr.
.flatpickr-calendar {
background: $gray-700;
color: $body-color;
box-shadow: 1px 0 0 $gray-600, -1px 0 0 $gray-600, 0 1px 0 $gray-600, 0 -1px 0 $gray-600,
0 3px 13px rgb(0 0 0 / 8%);
border-radius: $border-radius;
& span.flatpickr-weekday {
color: $gray-400;
}
&.arrowTop:before,
&.arrowTop:after {
border-bottom-color: $gray-700;
}
.flatpickr-months {
& .flatpickr-month {
color: $body-color;
fill: $body-color;
}
& .flatpickr-next-month,
& .flatpickr-prev-month {
color: $body-color;
fill: $body-color;
}
.flatpickr-current-month .flatpickr-monthDropdown-months {
background: $gray-700;
}
}
.flatpickr-day {
color: $body-color;
&.today {
border-color: $gray-200;
}
&.selected,
&.startRange,
&.endRange,
&.selected.inRange,
&.startRange.inRange,
&.endRange.inRange,
&.selected:focus,
&.startRange:focus,
&.endRange:focus,
&.selected:hover,
&.startRange:hover,
&.endRange:hover,
&.selected.prevMonthDay,
&.startRange.prevMonthDay,
&.endRange.prevMonthDay,
&.selected.nextMonthDay,
&.startRange.nextMonthDay,
&.endRange.nextMonthDay {
background: $blue-300;
border-color: $blue-300;
color: color-contrast($blue-300);
}
&:hover {
border-color: $gray-200;
background: $gray-200;
color: color-contrast($gray-200);
}
&.flatpickr-disabled,
&.flatpickr-disabled:hover,
&.prevMonthDay,
&.nextMonthDay,
&.notAllowed,
&.notAllowed.prevMonthDay,
&.notAllowed.nextMonthDay {
color: $gray-500;
}
}
}

View File

@ -1,3 +1,7 @@
// Main Entry Point for all Netbox Styles.
// Note: The order of these imports is critical for proper inheritance.
// Light Mode Styles.
@import './theme-light.scss'; @import './theme-light.scss';
@import './bootstrap.scss'; @import './bootstrap.scss';
@ -8,6 +12,7 @@
@import './netbox.scss'; @import './netbox.scss';
// Dark Mode Styles.
body[data-netbox-color-mode='dark'] { body[data-netbox-color-mode='dark'] {
@import './theme-dark.scss'; @import './theme-dark.scss';
@import './bootstrap.scss'; @import './bootstrap.scss';
@ -16,6 +21,7 @@ body[data-netbox-color-mode='dark'] {
@import './select.scss'; @import './select.scss';
@import 'flatpickr/dist/flatpickr.css'; @import 'flatpickr/dist/flatpickr.css';
@import './flatpickr-dark.scss';
@import './netbox.scss'; @import './netbox.scss';
} }

View File

@ -1,3 +1,7 @@
// Netbox-specific Styles and Overrides.
@use 'sass:map';
:root { :root {
--nbx-logo-color-1: #9cc8f8; --nbx-logo-color-1: #9cc8f8;
--nbx-logo-color-2: #1685fc; --nbx-logo-color-2: #1685fc;
@ -16,7 +20,6 @@
--nbx-cable-node-border-color: #{$gray-200}; --nbx-cable-node-border-color: #{$gray-200};
--nbx-cable-termination-bg: #{$gray-200}; --nbx-cable-termination-bg: #{$gray-200};
--nbx-cable-termination-border-color: #{$gray-300}; --nbx-cable-termination-border-color: #{$gray-300};
--nbx-elevation-slot-bg: #{$gray-100};
body[data-netbox-color-mode='dark'] { body[data-netbox-color-mode='dark'] {
--nbx-logo-color-1: #{$white}; --nbx-logo-color-1: #{$white};
@ -36,7 +39,6 @@
--nbx-cable-node-border-color: #{$gray-600}; --nbx-cable-node-border-color: #{$gray-600};
--nbx-cable-termination-bg: #{$gray-800}; --nbx-cable-termination-bg: #{$gray-800};
--nbx-cable-termination-border-color: #{$gray-700}; --nbx-cable-termination-border-color: #{$gray-700};
--nbx-elevation-slot-bg: #{$gray-700};
} }
} }
@ -92,6 +94,23 @@ body {
} }
} }
div.title-container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
align-items: center;
padding-top: $spacer * 2;
margin-bottom: $spacer * 2;
border-bottom: 1px solid $border-color;
div#content-title {
display: flex;
flex-direction: column;
flex: 1 0 auto;
padding-bottom: map.get($spacers, 2);
}
}
nav.search { nav.search {
background-color: var(--nbx-body-bg); background-color: var(--nbx-body-bg);
} }
@ -306,6 +325,7 @@ pre {
.card { .card {
box-shadow: $box-shadow-sm; box-shadow: $box-shadow-sm;
.card-header { .card-header {
color: $body-color;
border-bottom: none; border-bottom: none;
padding: $card-cap-padding-x; padding: $card-cap-padding-x;
} }
@ -413,6 +433,8 @@ nav.breadcrumb-container {
font-size: $font-size-sm; font-size: $font-size-sm;
width: fit-content; width: fit-content;
background-color: var(--nbx-breadcrumb-bg); background-color: var(--nbx-breadcrumb-bg);
margin-top: $spacer;
margin-bottom: $spacer;
ol.breadcrumb { ol.breadcrumb {
margin-bottom: 0; margin-bottom: 0;
@ -425,12 +447,6 @@ nav.breadcrumb-container {
} }
} }
div#content-title {
display: flex;
flex-direction: column;
flex: 1 0 auto;
}
div.paginator > form > div.input-group { div.paginator > form > div.input-group {
width: fit-content; width: fit-content;
} }

View File

@ -1,4 +1,4 @@
/* Stylesheet for rendering SVG rack elevations */ // Stylesheet for rendering SVG rack elevations
@import './theme-light.scss'; @import './theme-light.scss';
* { * {

View File

@ -1,3 +1,5 @@
// SlimSelect Style Overrides.
$height: $input-height; $height: $input-height;
$white: $white; $white: $white;
$font-color: $input-color; $font-color: $input-color;
@ -11,6 +13,19 @@ $spacing-l: $input-padding-x;
$spacing-m: $input-padding-x; $spacing-m: $input-padding-x;
$spacing-s: $input-padding-x; $spacing-s: $input-padding-x;
:root {
--nbx-select-content-bg: null;
--nbx-select-option-selected-bg: #{$gray-300};
--nbx-select-option-hover-bg: #{$blue};
--nbx-select-option-hover-color: #{$white};
& body[data-netbox-color-mode='dark'] {
--nbx-select-content-bg: #{$gray-900};
--nbx-select-option-selected-bg: #{$gray-500};
--nbx-select-option-hover-bg: #{$blue-200};
--nbx-select-option-hover-color: #{color-contrast($blue-200)};
}
}
div.form-floating div.ss-main div.ss-single-selected, div.form-floating div.ss-main div.ss-single-selected,
div.form-floating div.ss-main div.ss-multi-selected { div.form-floating div.ss-main div.ss-multi-selected {
height: $form-floating-height; height: $form-floating-height;
@ -73,14 +88,15 @@ div.form-floating div.ss-main div.ss-multi-selected {
} }
.ss-content { .ss-content {
background-color: $gray-900; background-color: var(--nbx-select-content-bg);
.ss-list { .ss-list {
.ss-option.ss-option-selected { .ss-option.ss-option-selected {
background-color: $gray-600; background-color: var(--nbx-select-option-selected-bg);
color: $white; color: $body-color;
} }
.ss-option:hover { .ss-option:hover {
background-color: $blue-400; background-color: var(--nbx-select-option-hover-bg);
color: var(--nbx-select-option-hover-color);
} }
.ss-option:last-child { .ss-option:last-child {
border-bottom-left-radius: $form-select-border-radius; border-bottom-left-radius: $form-select-border-radius;

View File

@ -1,12 +1,13 @@
import { createToast } from './bs'; import { createToast } from './bs';
import { setColorMode } from './colorMode';
import { import {
slugify,
isTruthy, isTruthy,
getElements,
apiPatch, apiPatch,
hasError, hasError,
slugify,
findFirstAdjacent,
getElement, getElement,
getElements,
findFirstAdjacent,
} from './util'; } from './util';
/** /**
@ -131,6 +132,34 @@ function initReslug(): void {
}); });
} }
/**
* Perform actions in the UI based on the value of user profile updates.
*
* @param event Form Submit
*/
function handlePreferenceSave(event: Event): void {
// Create a FormData instance to access the form values.
const form = event.currentTarget as HTMLFormElement;
const formData = new FormData(form);
// Update the UI color mode immediately when the user preference changes.
if (formData.get('ui.colormode') === 'dark') {
setColorMode('dark');
} else if (formData.get('ui.colormode') === 'light') {
setColorMode('light');
}
}
/**
* Initialize handlers for user profile updates.
*/
function initPreferenceUpdate() {
const form = getElement<HTMLFormElement>('preferences-update');
if (form !== null) {
form.addEventListener('submit', handlePreferenceSave);
}
}
/** /**
* Show the select all card when the select all checkbox is checked, and sync the checkbox state * Show the select all card when the select all checkbox is checked, and sync the checkbox state
* with all the PK checkboxes in the table. * with all the PK checkboxes in the table.
@ -237,7 +266,13 @@ function initSelectAll() {
} }
export function initButtons() { export function initButtons() {
for (const func of [initRackElevation, initConnectionToggle, initReslug, initSelectAll]) { for (const func of [
initRackElevation,
initConnectionToggle,
initReslug,
initSelectAll,
initPreferenceUpdate,
]) {
func(); func();
} }
} }

View File

@ -56,7 +56,7 @@ function updateElements(targetMode: ColorMode): void {
* *
* @param mode Target color mode. * @param mode Target color mode.
*/ */
function setColorMode(mode: ColorMode): void { export function setColorMode(mode: ColorMode): void {
for (const func of [storeColorMode, updateElements]) { for (const func of [storeColorMode, updateElements]) {
func(mode); func(mode);
} }

View File

@ -1,3 +1,4 @@
// Base Netbox Theme Overrides and Settings - color mode agnostic.
@import 'bootstrap/scss/functions'; @import 'bootstrap/scss/functions';
$alt: #13293d; $alt: #13293d;

View File

@ -1,3 +1,5 @@
// Dark Mode Theme Variables and Overrides.
@import './theme-base.scss'; @import './theme-base.scss';
$primary: $blue-300; $primary: $blue-300;
@ -54,24 +56,16 @@ $mark-bg: #fcf8e3;
// Tables // Tables
$table-color: $gray-100; $table-color: $gray-100;
$table-border-color: $border-color; $table-border-color: $border-color;
// $table-bg: transparent;
$table-striped-color: $table-color; $table-striped-color: $table-color;
$table-striped-bg: rgba($white, $table-striped-bg-factor); $table-striped-bg: rgba($white, $table-striped-bg-factor);
$table-active-color: $table-color; $table-active-color: $table-color;
$table-active-bg: rgba($white, $table-active-bg-factor); $table-active-bg: rgba($white, $table-active-bg-factor);
$table-hover-color: $table-color; $table-hover-color: $table-color;
$table-hover-bg: rgba($white, $table-hover-bg-factor); $table-hover-bg: rgba($white, $table-hover-bg-factor);
// $table-group-separator-color: currentColor;
// Buttons + Forms
// $input-btn-focus-color: rgba($component-active-bg, $input-btn-focus-color-opacity);
// $input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color;
// Buttons // Buttons
$btn-box-shadow: inset 0 1px 0 rgba($black, 0.15), 0 1px 1px rgba($white, 0.075); $btn-box-shadow: inset 0 1px 0 rgba($black, 0.15), 0 1px 1px rgba($white, 0.075);
$btn-active-box-shadow: inset 0 3px 5px rgba($white, 0.125); $btn-active-box-shadow: inset 0 3px 5px rgba($white, 0.125);
// $btn-link-color: $link-color;
// $btn-link-hover-color: $link-hover-color;
$btn-link-disabled-color: $gray-300; $btn-link-disabled-color: $gray-300;
// Forms // Forms
@ -144,18 +138,6 @@ $dropdown-link-hover-color: shade-color($gray-50, 10%);
$dropdown-link-hover-bg: $gray-500; $dropdown-link-hover-bg: $gray-500;
$dropdown-link-disabled-color: $gray-800; $dropdown-link-disabled-color: $gray-800;
$dropdown-header-color: $gray-300; $dropdown-header-color: $gray-300;
// $dropdown-dark-color: $gray-300;
// $dropdown-dark-bg: $gray-800;
// $dropdown-dark-border-color: $dropdown-border-color;
// $dropdown-dark-divider-bg: $dropdown-divider-bg;
// $dropdown-dark-box-shadow: null;
// $dropdown-dark-link-color: $dropdown-dark-color;
// $dropdown-dark-link-hover-color: $white;
// $dropdown-dark-link-hover-bg: rgba($white, .15);
// $dropdown-dark-link-active-color: $dropdown-link-active-color;
// $dropdown-dark-link-active-bg: $dropdown-link-active-bg;
// $dropdown-dark-link-disabled-color: $gray-500;
// $dropdown-dark-header-color: $gray-500;
// Pagination // Pagination
$pagination-color: $link-color; $pagination-color: $link-color;
@ -184,7 +166,7 @@ $card-bg: $gray-800;
// Accordion // Accordion
$accordion-color: $body-color; $accordion-color: $body-color;
// $accordion-bg: transparent; $accordion-bg: transparent;
$accordion-border-color: rgba($white, 0.125); $accordion-border-color: rgba($white, 0.125);
$accordion-button-color: $accordion-color; $accordion-button-color: $accordion-color;
$accordion-button-bg: $accordion-bg; $accordion-button-bg: $accordion-bg;
@ -200,7 +182,6 @@ $accordion-button-active-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3
// Tooltips // Tooltips
$tooltip-color: $body-color; $tooltip-color: $body-color;
$tooltip-bg: $gray-700; $tooltip-bg: $gray-700;
// $tooltip-opacity: .9;
$tooltip-arrow-color: $tooltip-bg; $tooltip-arrow-color: $tooltip-bg;
$form-feedback-tooltip-opacity: $tooltip-opacity; $form-feedback-tooltip-opacity: $tooltip-opacity;
@ -229,15 +210,9 @@ $modal-content-color: null;
$modal-content-bg: $gray-800; $modal-content-bg: $gray-800;
$modal-content-border-color: rgba($white, 0.2); $modal-content-border-color: rgba($white, 0.2);
$modal-backdrop-bg: $black; $modal-backdrop-bg: $black;
// $modal-backdrop-opacity: .5;
$modal-header-border-color: $border-color; $modal-header-border-color: $border-color;
$modal-footer-border-color: $modal-header-border-color; $modal-footer-border-color: $modal-header-border-color;
// Alerts
// $alert-bg-scale: -80%;
// $alert-border-scale: -70%;
// $alert-color-scale: 40%;
// Progress bars // Progress bars
$progress-bg: $gray-600; $progress-bg: $gray-600;
$progress-bar-color: $white; $progress-bar-color: $white;
@ -251,7 +226,6 @@ $list-group-hover-bg: rgba($gray-50, 0.15);
$list-group-active-color: $component-active-color; $list-group-active-color: $component-active-color;
$list-group-active-bg: $component-active-bg; $list-group-active-bg: $component-active-bg;
$list-group-active-border-color: $list-group-active-bg; $list-group-active-border-color: $list-group-active-bg;
// $list-group-disabled-color: $gray-600;
$list-group-disabled-bg: $list-group-bg; $list-group-disabled-bg: $list-group-bg;
$list-group-action-color: $gray-300; $list-group-action-color: $gray-300;
$list-group-action-hover-color: $body-color; $list-group-action-hover-color: $body-color;
@ -266,7 +240,6 @@ $thumbnail-border-color: $gray-300;
$figure-caption-color: $gray-600; $figure-caption-color: $gray-600;
// Breadcrumbs // Breadcrumbs
// $breadcrumb-bg: $gray-700;
$breadcrumb-divider-color: $gray-100; $breadcrumb-divider-color: $gray-100;
$breadcrumb-active-color: $body-color; $breadcrumb-active-color: $body-color;
$breadcrumb-divider-flipped: $breadcrumb-divider; $breadcrumb-divider-flipped: $breadcrumb-divider;

View File

@ -1,3 +1,5 @@
// Light Mode Theme Variables and Overrides.
@import './theme-base.scss'; @import './theme-base.scss';
$input-border-color: $gray-200; $input-border-color: $gray-200;
@ -13,4 +15,7 @@ $light: $gray-100;
$card-cap-color: $gray-800; $card-cap-color: $gray-800;
$accordion-bg: transparent;
$accordion-button-bg: $accordion-bg;
$breadcrumb-divider: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='currentColor'/%3E%3C/svg%3E"); $breadcrumb-divider: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='currentColor'/%3E%3C/svg%3E");

View File

@ -1,6 +1,7 @@
{% extends 'layout.html' %} {% load helpers %} {%block title %} Home {% extends 'layout.html' %}
{%endblock%} {% block content %} {% load helpers %}
{% block title_container %}{% endblock %}
{% block content %}
<div class="stats-container"> <div class="stats-container">
<div class="row row-cols-auto masonry"> <div class="row row-cols-auto masonry">
{% for section in stats %} {% for section in stats %}
@ -51,5 +52,4 @@
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -37,11 +37,10 @@
{% search_options %} {% include './profile_button.html' %} {% search_options %} {% include './profile_button.html' %}
</nav> </nav>
<div class="px-4"> <div class="px-4">
<div {% block title_container %}
class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom" <div class="title-container">
>
<div id="content-title"> <div id="content-title">
<h1 class="h2 w-100">{% block title %}{% endblock %}</h1> <h1 class="h2 w-100">{% block title %}{% endblock %}</h1>
{% block breadcrumb_main %}{% endblock %} {% block breadcrumb_main %}{% endblock %}
@ -49,6 +48,7 @@
{% block controls %}{% endblock %} {% block controls %}{% endblock %}
</div> </div>
{% endblock %}
<div id="content" class="container-fluid p-0 m-0"> <div id="content" class="container-fluid p-0 m-0">
{% block tabs %}{% endblock %} {% block tabs %}{% endblock %}
{% block content %}{% endblock %} {% block content %}{% endblock %}

View File

@ -4,11 +4,11 @@
{% block title %}User Preferences{% endblock %} {% block title %}User Preferences{% endblock %}
{% block usercontent %} {% block usercontent %}
<form method="post" action=""> <form method="post" action="" id="preferences-update">
{% csrf_token %} {% csrf_token %}
<div class="field-group mb-3"> <div class="field-group mb-3">
<h4>Color Mode</h4> <h4>Color Mode</h4>
<p class="lead text-muted">Set your preferred UI color mode</p> <p class="lead text-muted">Set preferred UI color mode</p>
{% with color_mode=preferences|get_key:'ui.colormode'%} {% with color_mode=preferences|get_key:'ui.colormode'%}
<div class="form-check form-check-inline"> <div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="ui.colormode" id="color-mode-preference-dark" value="dark"{% if color_mode == 'dark'%} checked{% endif %}> <input class="form-check-input" type="radio" name="ui.colormode" id="color-mode-preference-dark" value="dark"{% if color_mode == 'dark'%} checked{% endif %}>
@ -22,18 +22,18 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<button type="submit" class="btn btn-success" name="_update"> <button type="submit" class="btn btn-primary" name="_update">
Save Save
</button> </button>
</div> </div>
</div> </div>
{% if preferences %} {% if preferences %}
<div class="field-group"> <div class="field-group mb-3">
<h4>Other Preferences</h4> <h4>Other Preferences</h4>
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
<th><input type="checkbox" class="toggle" title="Toggle all"></th> <th><input type="checkbox" class="toggle form-check-input" title="Toggle All"></th>
<th>Preference</th> <th>Preference</th>
<th>Value</th> <th>Value</th>
</tr> </tr>
@ -41,7 +41,7 @@
<tbody> <tbody>
{% for key, value in preferences.items %} {% for key, value in preferences.items %}
<tr> <tr>
<td class="min-width"><input type="checkbox" name="pk" value="{{ key }}"></td> <td class="min-width"><input class="form-check-input" type="checkbox" name="pk" value="{{ key }}"></td>
<td><samp>{{ key }}</samp></td> <td><samp>{{ key }}</samp></td>
<td><samp>{{ value }}</samp></td> <td><samp>{{ value }}</samp></td>
</tr> </tr>
@ -53,7 +53,7 @@
</button> </button>
</div> </div>
{% else %} {% else %}
<h3 class="text-muted text-center">No preferences found</h3> <h3 class="text-muted text-center">No Preferences Found</h3>
{% endif %} {% endif %}
</form> </form>
{% endblock %} {% endblock %}