Added Color Theme view in settings

This commit is contained in:
eeintech 2020-09-07 11:29:24 -05:00
parent f0713ce01d
commit 0548bee8ad
8 changed files with 875 additions and 5 deletions

View File

@ -11,7 +11,7 @@ from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Field
from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppendedText
from django.contrib.auth.models import User
from common.models import Theme
class HelperForm(forms.ModelForm):
""" Provides simple integration of crispy_forms extension. """
@ -161,3 +161,14 @@ class SetPasswordForm(HelperForm):
'enter_password',
'confirm_password'
]
class ThemeSelectForm(forms.ModelForm):
""" Form for setting color theme
"""
class Meta:
model = Theme
fields = [
'theme'
]

View File

@ -0,0 +1,785 @@
:root {
--primary-color: #335d88;
--secondary-color: #b69c80;
--highlight-color: #f5efe8;
--basic-color: #333;
--label-red: #e35a57;
--label-blue: #4194bd;
--label-green: #50aa51;
--label-grey: #aaa;
--label-yellow: #fdc82a;
}
.markdownx .row {
margin: 5px;
padding: 5px;
border: 1px solid #cce;
border-radius: 4px;
}
.markdownx-editor {
width: 100%;
border: 1px solid #cce;
border-radius: 3px;
padding: 10px;
}
.panel-content {
padding: 10px;
}
.markdownx-preview {
border: 1px solid #cce;
border-radius: 3px;
padding: 10px;
}
/* Progress bars */
.progress {
position: relative;
width: 100%;
margin-bottom: 0px;
background: #eeeef5;
}
.progress-bar {
opacity: 60%;
background: #2aa02a;
}
.progress-bar-under {
background: #eeaa33;
}
.progress-bar-over {
background: #337ab7;
}
.progress-value {
width: 100%;
color: #333;
position: absolute;
text-align: center;
top: 0px;
left: 0px;
font-size: 110%;
}
.qr-code {
max-width: 400px;
max-height: 400px;
align-content: center;
}
.qr-container {
width: 100%;
align-content: center;
}
.navbar-brand {
float: left;
}
.navbar-barcode-li {
border-left: none;
border-right: none;
}
.navbar-nav > li {
border-left: 1px solid;
border-right: 1px solid;
border-color: rgb(179, 179, 179);
}
.navbar-nav > li > a {
color:#0b2a62 !important;
}
.navbar-nav > li > a:hover {
color:#202020 !important;
}
.navbar-nav > .open > a {
color:#202020 !important;
}
.navbar-form {
padding-right: 3px;
}
.navbar {
background-color: rgb(189, 189, 189);
}
.table-condensed > tbody > tr > td {
border-top: 1px solid #062152 !important ;
}
.table-striped > tbody > tr > td {
border-top: 1px solid #92b3f1 ;
}
.table-bordered, .table-bordered > tbody > tr > td {
border: 1px solid rgb(182,182,182);
}
.table-bordered > thead > tr > th {
border: 1px solid rgb(182, 182, 182);
background-color: rgb(235, 235, 235);
}
h3 {
color:#06255d;
}
#barcode-scan {
margin-top: 8px;
}
.icon-header {
margin-right: 10px;
}
.glyphicon {
font-size: 18px;
}
.glyphicon-small {
font-size: 12px;
}
.glyphicon-right {
float: right;
}
.starred-part {
color: #ffbb00;
}
.red-cell {
background-color: #ec7f7f;
}
.part-price {
color: rgb(13, 245, 25);
}
.icon-red {
color: #c55;
}
.icon-green {
color: #43bb43;
}
.icon-blue {
color: #55c;
}
.icon-yellow {
color: #CC2;
}
/* CSS overrides for treeview */
.expand-icon {
font-size: 11px;
}
.treeview .badge {
font-size: 10px;
}
.treeview .list-group-item {
padding: 6px 12px;
}
.list-group-item-condensed {
padding: 5px 10px;
}
/* Extra label styles */
.label-large {
margin: 3px;
font-size: 100%;
border: 3px solid;
border-radius: 15px;
background: none;
padding-right: 10px;
padding-left: 10px;
padding-top: 5px;
padding-bottom: 5px;
}
.label-large-red {
color: var(--label-red);
border-color: var(--label-red);
}
.label-red {
background: var(--label-red);
}
.label-large-blue {
color: var(--label-blue);
border-color: var(--label-blue);
}
.label-blue {
background: var(--label-blue);
}
.label-large-green {
color: var(--label-green);
border-color: var(--label-green);
}
.label-green {
background: var(--label-green);
}
.label-large-grey {
color: var(--label-grey);
border-color: var(--label-grey);
}
.label-grey {
background: var(--label-grey);
}
.label-large-yellow {
color: var(--label-yellow);
border-color: var(--label-yellow);
}
.label-yellow {
background: var(--label-yellow);
}
.label-right {
float: right;
margin-left: 3px;
margin-right: 3px;
}
/* Bootstrap table overrides */
.stock-sub-group td {
background-color: #ebf4f4;
}
.sub-table {
margin-left: 45px;
margin-right: 45px;
}
.detail-icon .glyphicon {
color: #98d296;
}
/* Force select2 elements in modal forms to be full width */
.select-full-width {
width: 100%;
}
.basecurrency {
color: #050;
font-style: italic;
font-weight: bold;
}
.bomselect {
max-width: 250px;
}
.rowvalid {
color: #050;
}
.rowinvalid {
color: #A00;
font-style: italic;
}
.dropdown {
padding-left: 1px;
margin-left: 1px;
}
.dropdown-buttons {
display: inline-block
}
.dropdown-menu .open{
z-index: 1000;
position: relative;
overflow: visible;
}
/* Styles for table buttons and filtering */
.button-toolbar .btn {
margin-left: 1px;
margin-right: 1px;
}
.filter-list {
display: inline-block;
*display: inline;
margin-bottom: 1px;
margin-top: 1px;
vertical-align: middle;
margin: 1px;
padding: 2px;
background: #eee;
border: 1px solid #eee;
border-radius: 3px;
}
.filter-list .close {
cursor: pointer;
right: 0%;
padding-right: 2px;
padding-left: 2px;
transform: translate(0%, -25%);
}
.filter-list .close:hover {background: #bbb;}
.filter-tag {
display: inline-block;
*display: inline;
zoom: 1;
padding-left: 3px;
padding-right: 3px;
padding-top: 2px;
padding-bottom: 2px;
border: 1px solid #aaa;
border-radius: 3px;
background: #eee;
margin: 1px;
margin-left: 5px;
margin-right: 5px;
}
.filter-input {
display: inline-block;
*display: inline;
zoom: 1;
}
.filter-tag:hover {
background: #ddd;
}
/* Part image icons with full-display on mouse hover */
.hover-img-thumb {
background: #eee;
width: 28px;
height: 28px;
object-fit: contain;
border: 1px solid #cce;
}
.hover-img-large {
background: #eee;
display: none;
position: absolute;
z-index: 400;
border: 1px solid #555;
max-width: 250px;
}
.hover-icon {
margin-right: 10px;
}
.hover-icon:hover > .hover-img-large {
display: block;
}
/* dropzone class - for Drag-n-Drop file uploads */
.dropzone {
z-index: 2;
}
/*
.dropzone * {
pointer-events: none;
}
*/
.dragover {
background-color: #55A;
border: 1px dashed #111;
opacity: 0.1;
-moz-opacity: 10%;
-webkit-opacity: 10%;
}
/* grid display for part images */
.table-img-grid tr {
display: inline;
}
.table-img-grid td {
padding: 10px;
margin: 10px;
}
.table-img-grid .grid-image {
height: 128px;
width: 128px;
object-fit: contain;
background: #eee;
}
.btn-glyph {
padding-left: 6px;
padding-right: 6px;
padding-top: 3px;
padding-bottom: 2px;
}
.action-button {
font-size: 125%;
}
.action-buttons .btn {
font-size: 175%;
align-content: center;
vertical-align: middle;
padding-left: 6px;
padding-right: 6px;
padding-top: 3px;
padding-bottom: 2px;
};
.panel-heading .badge {
float: right;
}
.badge {
float: right;
background-color: #777;
color: #fff;
border-radius: 5px;
margin-left: 10px;
}
.badge-alert {
background-color: #f33;
}
.part-thumb {
width: 200px;
height: 200px;
margin: 2px;
padding: 3px;
object-fit: contain;
border: 1px solid #aaa;
border-radius: 3px;
}
.part-thumb-container:hover .part-thumb-overlay {
opacity: 1;
}
.part-thumb-overlay {
position: absolute;
top: 0;
left: 0;
opacity: 0;
transition: .25s ease;
padding: 15px;
margin: 5px;
}
.checkbox {
margin-left: 20px;
}
.checkboxinput {
padding-left: 5px;
padding-right: 5px;
}
.media {
padding-top: 15px;
}
.media-body {
padding-top: 10px;
overflow: visible;
}
.navigation {
}
.nav-tabs {
margin-bottom: 20px;
}
.settings-container {
width: 90%;
padding: 15px;
}
.settings-nav {
height: 100%;
width: 160px;
position: fixed;
z-index: 1;
//top: 0;
//left: 0;
overflow-x: hidden;
padding-top: 20px;
padding-right: 25px;
}
.settings-content {
margin-left: 175px;
padding: 0px 10px;
}
.breadcrump {
margin-bottom: 5px;
}
.inventree-body {
width: 100%;
padding: 5px;
margin: 10px;
}
.inventree-pre-content {
width: 100%;
clear: both;
}
.inventree-content {
padding-left: 5px;
padding-right: 5px;
padding-top: 5px;
width: auto;
transition: 0.1s;
}
.body {
padding-top: 70px;
}
.modal {
overflow: hidden;
z-index: 9999;
}
.modal-primary {
z-index: 10000;
}
.modal-secondary {
z-index: 11000;
}
.js-modal-form .checkbox {
margin-left: 0px;
}
.modal-dialog {
width: 60%;
}
.modal-secondary .modal-dialog {
width: 40%;
padding-top: 15px;
}
.modal-content h3 {
margin-top: 3px;
margin-bottom: 3px;
}
.modal-form-content {
border-radius: 0;
position:relative;
height: auto !important;
max-height: calc(100vh - 200px) !important;
overflow-y: scroll;
padding: 10px;
}
.modal input {
width: 100%;
}
input[type="submit"] {
color: #333;
background-color: #e6e6e6;
border-color: #adadad;
}
.modal textarea {
width: 100%;
}
/* Force a control-label div to be 100% width */
.modal .control-label {
width: 100%;
margin-top: 5px;
}
.modal .control-label .btn {
padding-top: 3px;
padding-bottom: 3px;
}
.modal .btn-secondary {
background-color: #5e7d87;
}
/* The side navigation menu */
.sidenav {
height: 100%; /* 100% Full-height */
width: 0px; /* 0 width - change this with JavaScript */
position: fixed; /* Stay in place */
background-color: #fff; /* Black*/
overflow-x: hidden; /* Disable horizontal scroll */
transition: 0.1s; /* 0.5 second transition effect to slide in the sidenav */
}
.wrapper {
align-items: stretch;
display: flex;
}
.help-inline {
color: #A11;
}
.notification-area {
position: fixed;
top: 0px;
margin-top: 20px;
width: 100%;
padding: 20px;
z-index: 5000;
pointer-events: none; // Prevent this div from blocking links underneath
}
.alert {
display: none;
border-radius: 5px;
opacity: 0.9;
pointer-events: all;
}
.alert-block {
display: block;
}
.btn {
margin-left: 2px;
margin-right: 2px;
}
.btn-remove {
padding: 3px;
padding-left: 5px;
padding-right: 5px;
color: #A11;
}
.btn-create {
padding: 3px;
padding-left: 5px;
padding-right: 5px;
color: #1A1;
}
.btn-edit {
padding: 3px;
padding: 3px;
padding-left: 5px;
padding-right: 5px;
color: #55E;
}
.button-toolbar {
padding-left: 0px;
}
.panel-group {
margin-bottom: 5px;
}
.panel-body {
padding: 10px;
}
.panel-group .panel {
border-radius: 2px;
}
.panel-heading {
padding: 5px 10px;
background-color: #fafafa;
}
.float-right {
float: right;
}
.warning-msg {
color: #e00;
}
.login {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.part-allocation {
padding: 3px 10px;
border: 1px solid #ccc;
border-radius: 2px;
}
.part-allocation-pass {
background-color: #dbf0db;
}
.part-allocation-underallocated {
background-color: #f0dbdb;
}
.part-allocation-overallocated {
background-color: #ccf5ff;
}
.glyphicon-refresh-animate {
-animation: spin .7s infinite linear;
-webkit-animation: spin2 .7s infinite linear;
}
@-webkit-keyframes spin2 {
from { -webkit-transform: rotate(0deg);}
to { -webkit-transform: rotate(360deg);}
}
@keyframes spin {
from { transform: scale(1) rotate(0deg);}
to { transform: scale(1) rotate(360deg);}
}

View File

@ -36,7 +36,7 @@ from django.views.generic.base import RedirectView
from rest_framework.documentation import include_docs_urls
from .views import IndexView, SearchView, DatabaseStatsView
from .views import SettingsView, EditUserView, SetPasswordView
from .views import SettingsView, EditUserView, SetPasswordView, ThemeSelectView
from .views import DynamicJsView
from .api import InfoView
@ -71,6 +71,7 @@ settings_urls = [
url(r'^user/?', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings-user'),
url(r'^currency/?', SettingsView.as_view(template_name='InvenTree/settings/currency.html'), name='settings-currency'),
url(r'^part/?', SettingsView.as_view(template_name='InvenTree/settings/part.html'), name='settings-part'),
url(r'^theme/?', ThemeSelectView.as_view(), name='settings-theme'),
url(r'^other/?', SettingsView.as_view(template_name='InvenTree/settings/other.html'), name='settings-other'),
# Catch any other urls

View File

@ -11,16 +11,17 @@ from __future__ import unicode_literals
from django.utils.translation import gettext_lazy as _
from django.template.loader import render_to_string
from django.http import JsonResponse, HttpResponseRedirect
from django.urls import reverse_lazy
from django.views import View
from django.views.generic import UpdateView, CreateView
from django.views.generic import UpdateView, CreateView, FormView
from django.views.generic.base import TemplateView
from part.models import Part, PartCategory
from stock.models import StockLocation, StockItem
from common.models import InvenTreeSetting
from common.models import InvenTreeSetting, Theme
from .forms import DeleteForm, EditUserForm, SetPasswordForm
from .forms import DeleteForm, EditUserForm, SetPasswordForm, ThemeSelectForm
from .helpers import str2bool
from rest_framework import views
@ -556,6 +557,14 @@ class SettingsView(TemplateView):
return ctx
class ThemeSelectView(FormView):
""" View for selecting a color theme """
form_class = ThemeSelectForm
success_url = reverse_lazy('settings-theme')
template_name = "InvenTree/settings/theme.html"
class DatabaseStatsView(AjaxView):
""" View for displaying database statistics """

View File

@ -0,0 +1,20 @@
# Generated by Django 3.0.7 on 2020-09-07 16:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('common', '0006_auto_20200203_0951'),
]
operations = [
migrations.CreateModel(
name='Theme',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('theme', models.IntegerField(choices=[(0, 'Default'), (1, 'Darker')], default=0)),
],
),
]

View File

@ -154,3 +154,17 @@ class Currency(models.Model):
self.value = 1.0
super().save(*args, **kwargs)
class Theme(models.Model):
""" Color Theme setting """
class ThemeChoices(models.IntegerChoices):
DEFAULT = 0, _('Default')
DARKER = 1, _('Darker')
theme = models.IntegerField(choices=ThemeChoices.choices,
default=ThemeChoices.DEFAULT)
def __str__(self):
return self.theme

View File

@ -8,6 +8,9 @@
<li{% ifequal tab 'part' %} class='active'{% endifequal %}>
<a href="{% url 'settings-part' %}"><span class='fas fa-shapes'></span> Part</a>
</li>
<li{% ifequal tab 'theme' %} class='active'{% endifequal %}>
<a href="{% url 'settings-theme' %}"><span class='fas fa-fill'></span> Theme</a>
</li>
{% if user.is_staff %}
<li{% ifequal tab 'other' %} class='active'{% endifequal %}>
<a href="{% url 'settings-other' %}"><span class='fas fa-cogs'></span> Other</a>

View File

@ -0,0 +1,27 @@
{% extends "InvenTree/settings/settings.html" %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='theme' %}
{% endblock %}
{% block settings %}
<div class='row'>
<div class='col-sm-6'>
<h4>Color Themes</h4>
</div>
</div>
<div class='row'>
<div class='col-sm-6'>
<div style='float: left;'>
<form action="{% url 'settings-theme' %}" method="post">
{% csrf_token %}
{{ form }}
<input class='btn btn-primary' type="submit" value='Apply Theme'>
</form>
</div>
</div>
</div>
{% endblock %}