mirror of
https://github.com/retspen/webvirtcloud
synced 2024-11-01 03:54:15 +00:00
Add Settings page: Move theme & lang changer to settings page
This commit is contained in:
parent
7409c197ed
commit
2d5c701789
16 changed files with 279 additions and 60 deletions
|
@ -112,44 +112,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{% if request.user.is_superuser %}
|
|
||||||
<h3 class="page-header">{% trans "Themes" %}</h3>
|
|
||||||
<form method="post" action="" role="form">{% csrf_token %}
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 col-form-label">{% trans "Themes" %}</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<select class="custom-select" name="theme_select" id="theme_select">
|
|
||||||
{% for theme in themes_list %}
|
|
||||||
<option value="{{ theme }}">{{ theme }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
<label>{% trans "Current Theme" %}:</label>
|
|
||||||
<label id="active_theme"></label>
|
|
||||||
</div>
|
|
||||||
<p class="text-muted">{% trans "After change please full refresh page with Ctrl + F5 "%}</p>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-sm-10">
|
|
||||||
<button type="submit" class="btn btn-primary" name="change_theme" onclick="reloadStylesheets()">{% trans "Change" %}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block script %}
|
|
||||||
<script>
|
|
||||||
$(document).ready(function (){
|
|
||||||
$('#active_theme').text(localStorage.getItem('active_theme'));
|
|
||||||
});
|
|
||||||
function reloadStylesheets() {
|
|
||||||
var selected_theme = $('#theme_select option').filter(':selected').val();
|
|
||||||
var queryString = '?reload=' + selected_theme;
|
|
||||||
$('#wvc_css').each(function () {
|
|
||||||
this.href = this.href.replace(/\?.*|$/, queryString);
|
|
||||||
});
|
|
||||||
localStorage.setItem('active_theme', selected_theme);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
0
appsettings/__init__.py
Normal file
0
appsettings/__init__.py
Normal file
3
appsettings/admin.py
Normal file
3
appsettings/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
5
appsettings/apps.py
Normal file
5
appsettings/apps.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class AppsettingsConfig(AppConfig):
|
||||||
|
name = 'appsettings'
|
24
appsettings/migrations/0001_initial.py
Normal file
24
appsettings/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Generated by Django 2.2.12 on 2020-05-23 15:53
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='AppSettings',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=25)),
|
||||||
|
('key', models.CharField(max_length=50, unique=True)),
|
||||||
|
('value', models.CharField(max_length=25)),
|
||||||
|
('description', models.CharField(max_length=100, null=True)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
80
appsettings/migrations/0002_auto_20200523_1553.py
Normal file
80
appsettings/migrations/0002_auto_20200523_1553.py
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
# Generated by Django 2.2.12 on 2020-05-23 12:05
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
def add_default_settings(apps, schema_editor):
|
||||||
|
|
||||||
|
setting = apps.get_model("appsettings", "AppSettings")
|
||||||
|
db_alias = schema_editor.connection.alias
|
||||||
|
setting.objects.using(db_alias).bulk_create([
|
||||||
|
setting(1, "Console Type", "QEMU_CONSOLE_DEFAULT_TYPE", "vnc", "Default console type"),
|
||||||
|
setting(2, "Libvirt K.alive Intrval", "LIBVIRT_KEEPALIVE_INTERVAL", "5", "libvirt keepalive interval"),
|
||||||
|
setting(3, "Libvirt K.alive Count", "LIBVIRT_KEEPALIVE_COUNT", "5", "libvirt keepalive count"),
|
||||||
|
setting(4, "Multiple Owner for VM ", "ALLOW_INSTANCE_MULTIPLE_OWNER", "True"),
|
||||||
|
setting(5, "VM Clone Name Prefix", "CLONE_INSTANCE_DEFAULT_PREFIX", "instance"),
|
||||||
|
setting(6, "VM Clone Auto Name", "CLONE_INSTANCE_AUTO_NAME", "False"),
|
||||||
|
setting(7, "VM Clone Auto Migrate", "CLONE_INSTANCE_AUTO_MIGRATE", "False"),
|
||||||
|
setting(8, "Logs per Page", "LOGS_PER_PAGE", "100"),
|
||||||
|
setting(9, "Quota Debug", "QUOTA_DEBUG", "True"),
|
||||||
|
setting(10, "Empty Password", "ALLOW_EMPTY_PASSWORD", "True"),
|
||||||
|
setting(11, "Account View Style", "VIEW_ACCOUNTS_STYLE", "grid", "available: default (grid), list"),
|
||||||
|
setting(12, "Instance List View", "VIEW_INSTANCES_LIST_STYLE", "grouped", "available instance list style: default (grouped), nongrouped"),
|
||||||
|
setting(13, "Show Bottom Bar", "VIEW_INSTANCE_DETAIL_BOTTOM_BAR", "True", "available options: True, False"),
|
||||||
|
setting(14, "Disk Format", "INSTANCE_VOLUME_DEFAULT_FORMAT", "qcow2", "available volume format: raw, qcow2, qcow"),
|
||||||
|
setting(15, "Disk Bus", "INSTANCE_VOLUME_DEFAULT_BUS", "virtio", "available bus types: virtio, scsi, ide, usb, sata"),
|
||||||
|
setting(16, "Disk SCSI Controller", "INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER", "virtio-scsi", "SCSI Types: virtio-scsi, lsilogic"),
|
||||||
|
setting(17, "Disk Cache", "INSTANCE_VOLUME_DEFAULT_CACHE", "directsync", " Volume cache: default, directsync, none, unsafe, writeback, writethrough"),
|
||||||
|
setting(18, "Disk IO Type", "INSTANCE_VOLUME_DEFAULT_IO", "default", "Volume io mode: default, native, threads"),
|
||||||
|
setting(19, "Disk Detect Zeroes", "INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES", "default", "Volume detect zeroes mode: default, on, off, unmap"),
|
||||||
|
setting(20, "Disk Discard", "INSTANCE_VOLUME_DEFAULT_DISCARD", "default", "Volume discard mode: default, unmap, ignore"),
|
||||||
|
setting(21, "Disk Owner UID", "INSTANCE_VOLUME_DEFAULT_OWNER_UID", "0", "up to os, 0=root, 107=qemu or libvirt-bin(for ubuntu)"),
|
||||||
|
setting(22, "Disk Owner GID", "INSTANCE_VOLUME_DEFAULT_OWNER_GID", "0", "up to os, 0=root, 107=qemu or libvirt-bin(for ubuntu)"),
|
||||||
|
setting(23, "CPU Mode", "INSTANCE_CPU_DEFAULT_MODE", "host-model", "Cpu modes: no-model, host-model, host-passthrough, custom"),
|
||||||
|
setting(24, "Machine Type", "INSTANCE_MACHINE_DEFAULT_TYPE", "q35", "Chipset/Machine: pc or q35 for x86_64"),
|
||||||
|
setting(25, "Firmware Type", "INSTANCE_FIRMWARE_DEFAULT_TYPE", "BIOS", "Firmware: BIOS or UEFI for x86_64"),
|
||||||
|
setting(26, "Architecture Type", "INSTANCE_ARCH_DEFAULT_TYPE", "x86_64", "Architecture: x86_64, i686, etc"),
|
||||||
|
setting(27, "Theme", "BOOTSTRAP_THEME", "", "Bootstrap CSS & Bootswatch"),
|
||||||
|
setting(28, "Sass Path", "SASS_DIR", "", "Bootstrap SASS & Bootswatch SASS "),
|
||||||
|
])
|
||||||
|
|
||||||
|
def del_default_settings(apps, schema_editor):
|
||||||
|
setting = apps.get_model("appsettings", "AppSettings")
|
||||||
|
db_alias = schema_editor.connection.alias
|
||||||
|
setting.objects.using(db_alias).filter(id=1, key="QEMU_CONSOLE_DEFAULT_TYPE").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=2, key="LIBVIRT_KEEPALIVE_INTERVAL").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=3, key="LIBVIRT_KEEPALIVE_COUNT").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=4, key="ALLOW_INSTANCE_MULTIPLE_OWNER").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=5, key="CLONE_INSTANCE_DEFAULT_PREFIX").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=6, key="CLONE_INSTANCE_AUTO_NAME").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=7, key="CLONE_INSTANCE_AUTO_MIGRATE").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=8, key="LOGS_PER_PAGE").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=9, key="QUOTA_DEBUG").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=10, key="ALLOW_EMPTY_PASSWORD").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=11, key="VIEW_ACCOUNTS_STYLE").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=12, key="VIEW_INSTANCES_LIST_STYLE").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=13, key="VIEW_INSTANCE_DETAIL_BOTTOM_BAR").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=14, key="INSTANCE_VOLUME_DEFAULT_FORMAT").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=15, key="INSTANCE_VOLUME_DEFAULT_BUS").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=16, key="INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=17, key="INSTANCE_VOLUME_DEFAULT_CACHE").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=18, key="INSTANCE_VOLUME_DEFAULT_IO").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=19, key="INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=20, key="INSTANCE_VOLUME_DEFAULT_DISCARD").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=21, key="INSTANCE_VOLUME_DEFAULT_OWNER_UID").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=22, key="INSTANCE_VOLUME_DEFAULT_OWNER_GID").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=23, key="INSTANCE_CPU_DEFAULT_MODE").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=24, key="INSTANCE_MACHINE_DEFAULT_TYPE").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=25, key="INSTANCE_FIRMWARE_DEFAULT_TYPE").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=26, key="INSTANCE_ARCH_DEFAULT_TYPE").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=27, key="BOOTSTRAP_THEME").delete()
|
||||||
|
setting.objects.using(db_alias).filter(id=28, key="SASS_DIR").delete()
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('appsettings', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(add_default_settings, del_default_settings),
|
||||||
|
]
|
0
appsettings/migrations/__init__.py
Normal file
0
appsettings/migrations/__init__.py
Normal file
8
appsettings/models.py
Normal file
8
appsettings/models.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class AppSettings(models.Model):
|
||||||
|
name = models.CharField(max_length=25, null=False)
|
||||||
|
key = models.CharField(max_length=50, unique=True)
|
||||||
|
value = models.CharField(max_length=25)
|
||||||
|
description=models.CharField(max_length=100, null=True)
|
72
appsettings/templates/appsettings.html
Normal file
72
appsettings/templates/appsettings.html
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{% trans "Edit Settings" %}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<!-- Page Heading -->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<h2 class="page-header">{% trans "Edit Settings" %}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /.row -->
|
||||||
|
|
||||||
|
{% include 'errors_block.html' %}
|
||||||
|
|
||||||
|
<div class="">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<h3 class="page-header">{% trans "App Settings" %}</h3>
|
||||||
|
<form action="{% url 'set_language' %}" method="post" style="display:inline">{% csrf_token %}
|
||||||
|
<div class="form-group row">
|
||||||
|
<input name="next" type="hidden" value="{{ redirect_to }}">
|
||||||
|
<label class="col-sm-3 col-form-label">{% trans "Language" %}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<select name="language" class="form-control" onchange="this.form.submit()">
|
||||||
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
|
{% get_available_languages as LANGUAGES %}
|
||||||
|
{% get_language_info_list for LANGUAGES as languages %}
|
||||||
|
{% for language in languages %}
|
||||||
|
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected{% endif %}>
|
||||||
|
{{ language.name_local }} ({{ language.code }})
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% if request.user.is_superuser %}
|
||||||
|
<form method="post" action="" role="form">{% csrf_token %}
|
||||||
|
<div class="form-group row">
|
||||||
|
<label class="col-sm-3 col-form-label">{{ sass_dir.name }}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input class="form-control" name="{{ sass_dir.key }}" value="{{ sass_dir.value }}" onchange="this.form.submit()"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form method="post" action="" role="form">{% csrf_token %}
|
||||||
|
<div class="form-group row">
|
||||||
|
<label class="col-sm-3 col-form-label">{% trans bootstrap_theme.name %}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<select class="form-control" name="{{ bootstrap_theme.key }}" onchange="this.form.submit()">
|
||||||
|
{% for theme in themes_list %}
|
||||||
|
<option {% if bootstrap_theme.value == theme %}selected{% endif %} value="{{ theme }}">{{ theme }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<span class="text-muted">{% trans "After change please full refresh page with Ctrl + F5 "%}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
<form method="post" action="" role="form">{% csrf_token %}
|
||||||
|
<div class="form-group row">
|
||||||
|
<label class="col-sm-3 col-form-label">{{ show_inst_bottom_bar.name }}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<select class="form-control" name="{{ show_inst_bottom_bar.key }}" onchange="this.form.submit()">
|
||||||
|
<option {% if show_inst_bottom_bar.value == 'True' %} selected {% endif %} value=True>{% trans "True" %}</option>
|
||||||
|
<option {% if show_inst_bottom_bar.value == 'False' %} selected {% endif %} value=False>{% trans "False" %}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
3
appsettings/tests.py
Normal file
3
appsettings/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
57
appsettings/views.py
Normal file
57
appsettings/views.py
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
from django.shortcuts import render
|
||||||
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.conf import settings
|
||||||
|
from appsettings.models import AppSettings
|
||||||
|
|
||||||
|
import sass
|
||||||
|
import os
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def appsettings(request):
|
||||||
|
"""
|
||||||
|
:param request:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
error_messages = []
|
||||||
|
|
||||||
|
|
||||||
|
show_inst_bottom_bar = AppSettings.objects.get(key="VIEW_INSTANCE_DETAIL_BOTTOM_BAR")
|
||||||
|
bootstrap_theme = AppSettings.objects.get(key="BOOTSTRAP_THEME")
|
||||||
|
sass_dir = AppSettings.objects.get(key="SASS_DIR")
|
||||||
|
|
||||||
|
themes_list = os.listdir(sass_dir.value + "/wvc-theme")
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
if 'BOOTSTRAP_THEME' in request.POST:
|
||||||
|
theme = request.POST.get("BOOTSTRAP_THEME", "")
|
||||||
|
scss_var = f"@import '{sass_dir.value}/wvc-theme/{theme}/variables';"
|
||||||
|
scss_bootswatch = f"@import '{sass_dir.value}/wvc-theme/{theme}/bootswatch';"
|
||||||
|
scss_boot = f"@import '{sass_dir.value}/bootstrap-overrides.scss';"
|
||||||
|
|
||||||
|
with open(sass_dir.value + "/wvc-main.scss", "w") as main:
|
||||||
|
main.write(scss_var + "\n" + scss_boot + "\n" + scss_bootswatch)
|
||||||
|
|
||||||
|
css_compressed = sass.compile(string=scss_var + "\n"+ scss_boot + "\n" + scss_bootswatch, output_style='compressed')
|
||||||
|
with open("static/" + "css/wvc-main.min.css", "w") as css:
|
||||||
|
css.write(css_compressed)
|
||||||
|
|
||||||
|
bootstrap_theme.value = theme
|
||||||
|
bootstrap_theme.save()
|
||||||
|
return HttpResponseRedirect(request.get_full_path())
|
||||||
|
|
||||||
|
if 'SASS_DIR' in request.POST:
|
||||||
|
sass_dir.value = request.POST.get("SASS_DIR", "")
|
||||||
|
sass_dir.save()
|
||||||
|
return HttpResponseRedirect(request.get_full_path())
|
||||||
|
|
||||||
|
if 'VIEW_INSTANCE_DETAIL_BOTTOM_BAR' in request.POST:
|
||||||
|
show_inst_bottom_bar.value = request.POST.get("VIEW_INSTANCE_DETAIL_BOTTOM_BAR", "")
|
||||||
|
show_inst_bottom_bar.save()
|
||||||
|
return HttpResponseRedirect(request.get_full_path())
|
||||||
|
|
||||||
|
|
||||||
|
return render(request, 'appsettings.html', locals())
|
||||||
|
|
|
@ -15,6 +15,7 @@ from computes.models import Compute
|
||||||
from instances.models import Instance
|
from instances.models import Instance
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from accounts.models import UserInstance, UserSSHKey
|
from accounts.models import UserInstance, UserSSHKey
|
||||||
|
from appsettings.models import AppSettings
|
||||||
from vrtManager.hostdetails import wvmHostDetails
|
from vrtManager.hostdetails import wvmHostDetails
|
||||||
from vrtManager.instance import wvmInstance, wvmInstances
|
from vrtManager.instance import wvmInstance, wvmInstances
|
||||||
from vrtManager.connection import connection_manager
|
from vrtManager.connection import connection_manager
|
||||||
|
@ -113,7 +114,7 @@ def instance(request, compute_id, vname):
|
||||||
keymaps = settings.QEMU_KEYMAPS
|
keymaps = settings.QEMU_KEYMAPS
|
||||||
console_types = settings.QEMU_CONSOLE_TYPES
|
console_types = settings.QEMU_CONSOLE_TYPES
|
||||||
console_listen_addresses = settings.QEMU_CONSOLE_LISTEN_ADDRESSES
|
console_listen_addresses = settings.QEMU_CONSOLE_LISTEN_ADDRESSES
|
||||||
bottom_bar = settings.VIEW_INSTANCE_DETAIL_BOTTOM_BAR
|
bottom_bar = AppSettings.objects.get(key="VIEW_INSTANCE_DETAIL_BOTTOM_BAR").value
|
||||||
try:
|
try:
|
||||||
userinstance = UserInstance.objects.get(instance__compute_id=compute_id,
|
userinstance = UserInstance.objects.get(instance__compute_id=compute_id,
|
||||||
instance__name=vname,
|
instance__name=vname,
|
||||||
|
|
|
@ -82,7 +82,6 @@
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
{% if state %}
|
{% if state %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h5 class="page-header mr-auto">{% trans "Volumes" %}</h5>
|
<h5 class="page-header mr-auto">{% trans "Volumes" %}</h5>
|
||||||
|
|
|
@ -17,19 +17,22 @@
|
||||||
<li class="nav-item {% class_active request '^/computes' %}">
|
<li class="nav-item {% class_active request '^/computes' %}">
|
||||||
<a class="nav-link" href="{% url 'computes' %}"><i class="fa fa-fw fa-server"></i> {% trans "Computes" %}</a>
|
<a class="nav-link" href="{% url 'computes' %}"><i class="fa fa-fw fa-server"></i> {% trans "Computes" %}</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
<ul class="navbar-nav navbar-right mt-2 mt-md-0">
|
||||||
|
{% if request.user.is_superuser %}
|
||||||
<li class="nav-item dropdown {% app_active request 'admin' %}">
|
<li class="nav-item dropdown {% app_active request 'admin' %}">
|
||||||
<a class="nav-link dropdown-toggle" id="administration" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<a class="nav-link" id="administration" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
{% trans "Administration" %}
|
{% icon 'wrench' %}
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu" aria-labelledby="administration">
|
<div class="dropdown-menu" aria-labelledby="administration">
|
||||||
<a class="dropdown-item {% view_active request 'admin:user_list' %}" href="{% url 'admin:user_list' %}">{% icon 'user-plus' %} {% trans "Users" %}</a>
|
<a class="dropdown-item {% view_active request 'admin:user_list' %}" href="{% url 'admin:user_list' %}">{% icon 'user-plus' %} {% trans "Users" %}</a>
|
||||||
<a class="dropdown-item {% view_active request 'admin:group_list' %}" href="{% url 'admin:group_list' %}">{% icon 'users' %} {% trans "Groups" %}</a>
|
<a class="dropdown-item {% view_active request 'admin:group_list' %}" href="{% url 'admin:group_list' %}">{% icon 'users' %} {% trans "Groups" %}</a>
|
||||||
<a class="dropdown-item {% view_active request 'admin:logs' %}" href="{% url 'admin:logs' %}">{% icon 'list-alt' %} {% trans "Logs" %}</a>
|
<a class="dropdown-item {% view_active request 'admin:logs' %}" href="{% url 'admin:logs' %}">{% icon 'list-alt' %} {% trans "Logs" %}</a>
|
||||||
</ul>
|
<a class="dropdown-item {% view_active request 'appsettings' %}" href="{% url 'appsettings' %}">{% icon 'cogs' %} {% trans "Settings" %}</i></a>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
|
||||||
<ul class="nav navbar-nav navbar-right">
|
|
||||||
<li class="nav-item dropdown {% class_active request '^/accounts' %}">
|
<li class="nav-item dropdown {% class_active request '^/accounts' %}">
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarUserDropdown" data-toggle="dropdown" role="button" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" href="#" id="navbarUserDropdown" data-toggle="dropdown" role="button" aria-expanded="false">
|
||||||
<i class="fa fa-fw fa-user"></i> {{ request.user.username }}
|
<i class="fa fa-fw fa-user"></i> {{ request.user.username }}
|
||||||
|
|
|
@ -35,6 +35,7 @@ INSTALLED_APPS = [
|
||||||
'nwfilters',
|
'nwfilters',
|
||||||
'storages',
|
'storages',
|
||||||
'secrets',
|
'secrets',
|
||||||
|
'appsettings',
|
||||||
'logs',
|
'logs',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -186,9 +187,6 @@ SHOW_ACCESS_SSH_KEYS = False
|
||||||
# available list style: default (grouped), nongrouped
|
# available list style: default (grouped), nongrouped
|
||||||
VIEW_INSTANCES_LIST_STYLE = 'grouped'
|
VIEW_INSTANCES_LIST_STYLE = 'grouped'
|
||||||
|
|
||||||
# available options: True, False
|
|
||||||
VIEW_INSTANCE_DETAIL_BOTTOM_BAR = True
|
|
||||||
|
|
||||||
# available volume format: raw, qcow2, qcow
|
# available volume format: raw, qcow2, qcow
|
||||||
INSTANCE_VOLUME_DEFAULT_FORMAT = 'qcow2'
|
INSTANCE_VOLUME_DEFAULT_FORMAT = 'qcow2'
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,17 @@ from django.urls import include, path
|
||||||
|
|
||||||
from instances.views import index
|
from instances.views import index
|
||||||
from console.views import console
|
from console.views import console
|
||||||
|
from appsettings.views import appsettings
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', index, name='index'),
|
path('', index, name='index'),
|
||||||
path('admin/', include(('admin.urls', 'admin'), namespace='admin')),
|
path('admin/', include(('admin.urls', 'admin'), namespace='admin')),
|
||||||
path('instances/', include('instances.urls')),
|
|
||||||
path('accounts/', include('accounts.urls')),
|
path('accounts/', include('accounts.urls')),
|
||||||
|
path('appsettings/', appsettings, name='appsettings'),
|
||||||
path('computes/', include('computes.urls')),
|
path('computes/', include('computes.urls')),
|
||||||
path('logs/', include('logs.urls')),
|
|
||||||
path('datasource/', include('datasource.urls')),
|
|
||||||
path('console/', console, name='console'),
|
path('console/', console, name='console'),
|
||||||
|
path('datasource/', include('datasource.urls')),
|
||||||
|
path('instances/', include('instances.urls')),
|
||||||
|
path('i18n/', include('django.conf.urls.i18n')),
|
||||||
|
path('logs/', include('logs.urls')),
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue