Commit 98757aa4 authored by 江世峰's avatar 江世峰

update assets_group

parent 8cdc4674
...@@ -17,7 +17,7 @@ class AssetForm(forms.ModelForm): ...@@ -17,7 +17,7 @@ class AssetForm(forms.ModelForm):
widgets = { widgets = {
'groups': forms.SelectMultiple(attrs={'class': 'select2-groups', 'data-placeholder': _('Select asset groups')}), 'groups': forms.SelectMultiple(attrs={'class': 'select2-groups', 'data-placeholder': _('Select asset groups')}),
'system_user': forms.SelectMultiple(attrs={'class': 'select2-system-user', 'data-placeholder': _('Select asset system user')}), 'system_users': forms.SelectMultiple(attrs={'class': 'select2-system-user', 'data-placeholder': _('Select asset system user')}),
# 'admin_user': forms.SelectMultiple(attrs={'class': 'select2-admin-user', 'data-placeholder': _('Select asset admin user')}), # 'admin_user': forms.SelectMultiple(attrs={'class': 'select2-admin-user', 'data-placeholder': _('Select asset admin user')}),
} }
...@@ -46,8 +46,13 @@ class AssetGroupForm(forms.ModelForm): ...@@ -46,8 +46,13 @@ class AssetGroupForm(forms.ModelForm):
class Meta: class Meta:
model = AssetGroup model = AssetGroup
fields = [ fields = [
"name", "comment" "name", "comment","system_users"
] ]
widgets = {
'name' : forms.TextInput(attrs={}),
'system_users': forms.SelectMultiple(attrs={'class': 'select2-system-user', 'data-placeholder': _('Select asset system user')}),
}
help_texts = { help_texts = {
'name': '* required', 'name': '* required',
} }
...@@ -76,11 +81,13 @@ class IDCForm(forms.ModelForm): ...@@ -76,11 +81,13 @@ class IDCForm(forms.ModelForm):
class Meta: class Meta:
model = IDC model = IDC
fields = ['name', "bandwidth", "operator", 'contact', 'phone', 'address', 'network', 'comment'] fields = ['name', "bandwidth", "operator", 'contact', 'phone', 'address', 'intranet', 'extranet','comment']
widgets = { widgets = {
'name': forms.TextInput(attrs={'placeholder': _('Name')}), 'name': forms.TextInput(attrs={'placeholder': _('Name')}),
'network': forms.Textarea( 'intranet': forms.Textarea(
attrs={'placeholder': '192.168.1.0/24\n192.168.2.0/24'}) attrs={'placeholder': 'IP段之间用逗号隔开,如:192.168.1.0/24,192.168.1.0/24'}),
'extranet': forms.Textarea(
attrs={'placeholder': 'IP段之间用逗号隔开,如:201.1.32.1/24,202.2.32.1/24'})
} }
......
...@@ -16,7 +16,8 @@ class IDC(models.Model): ...@@ -16,7 +16,8 @@ class IDC(models.Model):
contact = models.CharField(max_length=16, blank=True, verbose_name=_('Contact')) contact = models.CharField(max_length=16, blank=True, verbose_name=_('Contact'))
phone = models.CharField(max_length=32, blank=True, verbose_name=_('Phone')) phone = models.CharField(max_length=32, blank=True, verbose_name=_('Phone'))
address = models.CharField(max_length=128, blank=True, verbose_name=_("Address")) address = models.CharField(max_length=128, blank=True, verbose_name=_("Address"))
network = models.TextField(blank=True, verbose_name=_('Network')) intranet = models.TextField(blank=True, verbose_name=_('Intranet'))
extranet = models.TextField(blank=True, verbose_name=_('Extranet'))
date_created = models.DateTimeField(auto_now=True, null=True, verbose_name=_('Date added')) date_created = models.DateTimeField(auto_now=True, null=True, verbose_name=_('Date added'))
operator = models.CharField(max_length=32, blank=True, verbose_name=_('Operator')) operator = models.CharField(max_length=32, blank=True, verbose_name=_('Operator'))
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by')) created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
...@@ -235,7 +236,7 @@ class SystemUser(models.Model): ...@@ -235,7 +236,7 @@ class SystemUser(models.Model):
class AssetGroup(models.Model): class AssetGroup(models.Model):
name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) name = models.CharField(max_length=64, unique=True, verbose_name=_('Name'))
system_users = models.ManyToManyField(SystemUser, related_name='asset_groups', blank=True) system_users = models.ManyToManyField(SystemUser, related_name='system_users', blank=True)
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by')) created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
date_created = models.DateTimeField(auto_now=True, null=True, verbose_name=_('Date added')) date_created = models.DateTimeField(auto_now=True, null=True, verbose_name=_('Date added'))
comment = models.TextField(blank=True, verbose_name=_('Comment')) comment = models.TextField(blank=True, verbose_name=_('Comment'))
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
<p class="col-sm-offset-2">Tips: 管理用户是服务器存在的root或拥有sudo的用户,用来推送系统用户</p> <p class="col-sm-offset-2">Tips: 管理用户是服务器存在的root或拥有sudo的用户,用来推送系统用户</p>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
{{ form.system_user|bootstrap_horizontal }} {{ form.system_users|bootstrap_horizontal }}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<h3>所属</h3> <h3>所属</h3>
......
...@@ -6,50 +6,75 @@ ...@@ -6,50 +6,75 @@
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet"> <link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script> <script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5>{% trans 'Create asset group' %}</h5> <h5> {{ action }}</h5>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
</a> </a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
</div>
</div> </div>
<div class="ibox-content"> </div>
<form method="post" class="form-horizontal" action="" >
{% csrf_token %}
{{ form.name|bootstrap_horizontal }}
{{ form.assets|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }}
<div class="ibox-content">
<div class="panel blank-panel">
<div class="panel-body">
<div class="tab-content">
<div id="tab-1" class="ibox float-e-margins tab-pane active"></div>
<form id="IDCForm" method="post" class="form-horizontal">
{% csrf_token %}
<h3 class="widget-head-color-box">资产组信息</h3>
{{ form.name|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3 class="widget-head-color-box">资产</h3>
<div class="form-group"> <div class="form-group">
<div class="col-sm-4 col-sm-offset-2"> <label for="assets" class="col-sm-2 control-label">资产</label>
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button> <div class="col-sm-9">
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button> <select name="assets" id="assets" data-placeholder="选择资产" class="select2 form-control m-b" multiple tabindex="2">
{% for asset in assets %}
<option value="{{ asset.id }}">{{ asset.hostname }}</option>
{% endfor %}
</select>
</div> </div>
</div> </div>
</form> <!--{{ form.name|bootstrap_horizontal }}-->
<div class="hr-line-dashed"></div>
<h3 class="widget-head-color-box">资产用户</h3>
{{ form.system_users|bootstrap_horizontal }}
<div class="form-group">
<div class="col-sm-4 col-sm-offset-5">
<button class="btn btn-white" type="reset"> 重置 </button>
<button class="btn btn-primary" type="submit"> 提交 </button>
</div>
</div>
</form>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
$(document).ready(function () { $(document).ready(function () {
$('.select2').select2(); $('.select2').select2();
$('.select2-system-user').select2();
}) })
</script> </script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
</tr> </tr>
<tr> <tr>
<td>{% trans 'Date created' %}:</td> <td>{% trans 'Date created' %}:</td>
<td><b>{{ asset_group.date_created }}</b></td> <td><b>{{ asset_group.date_created|date:"Y-m-d H:i:s" }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Created by' %}:</td> <td>{% trans 'Created by' %}:</td>
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
<td class="text-center">{{ asset_group.comment|truncatewords:8 }}</td> <td class="text-center">{{ asset_group.comment|truncatewords:8 }}</td>
<td class="text-center"> <td class="text-center">
<a href="{% url 'assets:asset-group-update' pk=asset_group.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a> <a href="{% url 'assets:asset-group-update' pk=asset_group.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>
<a onclick="obj_del(this,'{{ asset_group.name }}','{% url 'assets:asset-group-delete' asset_group.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a> <a onclick="objectDelete(this,'{{ asset_group.name }}','{% url 'assets:asset-group-delete' asset_group.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
......
...@@ -6,52 +6,63 @@ ...@@ -6,52 +6,63 @@
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet"> <link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script> <script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5>{% trans 'Create idc' %}</h5> <h5> {{ action }}</h5>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
</a> </a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
</div>
</div> </div>
<div class="ibox-content"> </div>
<form method="post" class="form-horizontal" action="" >
{% csrf_token %} <div class="ibox-content">
{{ form.name|bootstrap_horizontal }} <div class="panel blank-panel">
{{ form.assets|bootstrap_horizontal }} <div class="panel-body">
{{ form.bandwidth|bootstrap_horizontal }} <div class="tab-content">
{{ form.operator|bootstrap_horizontal }} <div id="tab-1" class="ibox float-e-margins tab-pane active"></div>
{{ form.contact|bootstrap_horizontal }} <form id="IDCForm" method="post" class="form-horizontal">
{{ form.phone|bootstrap_horizontal }} {% csrf_token %}
{{ form.address|bootstrap_horizontal }} <h3 class="widget-head-color-box">基本信息</h3>
{{ form.network|bootstrap_horizontal }} {{ form.name|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }} {{ form.address|bootstrap_horizontal }}
{{ form.contact|bootstrap_horizontal }}
{{ form.phone|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3 class="widget-head-color-box">IP段</h3>
{{ form.intranet|bootstrap_horizontal }}
{{ form.extranet|bootstrap_horizontal }}
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2"> <div class="hr-line-dashed"></div>
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button> <div class="form-group">
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button> <div class="col-sm-4 col-sm-offset-5">
<button class="btn btn-white" type="reset"> 重置 </button>
<button class="btn btn-primary" type="submit"> 提交 </button>
</div>
</div>
</form>
</div> </div>
</div> </div>
</form> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
$(document).ready(function () { $(document).ready(function () {
......
...@@ -6,26 +6,31 @@ ...@@ -6,26 +6,31 @@
{% endblock %} {% endblock %}
{% block table_head %} {% block table_head %}
<th class="text-center">{% trans 'ID' %}</th> <th class="text-center">
<input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')">
</th>
{# <th class="text-center">{% trans 'ID' %}</th>#}
<th class="text-center"><a href="{% url 'assets:idc-list' %}?sort=name">{% trans 'Name' %}</a></th> <th class="text-center"><a href="{% url 'assets:idc-list' %}?sort=name">{% trans 'Name' %}</a></th>
<th class="text-center">{% trans 'Asset num' %}</th> <th class="text-center">{% trans 'Asset num' %}</th>
<th class="text-center">{% trans 'Bandwidth' %}</th> {# <th class="text-center">{% trans 'Bandwidth' %}</th>#}
<th class="text-center">{% trans 'Contact' %}</th> <th class="text-center">{% trans 'Contact' %}</th>
<th class="text-center">{% trans 'Phone' %}</th> <th class="text-center">{% trans 'Phone' %}</th>
<th class="text-center">{% trans 'Address' %}</th> {# <th class="text-center">{% trans 'Address' %}</th>#}
<th class="text-center"></th> <th class="text-center">{% trans 'operation' %}</th>
{% endblock %} {% endblock %}
{% block table_body %} {% block table_body %}
{% for idc in idc_list %} {% for idc in idc_list %}
<tr class="gradeX"> <tr class="gradeX">
<td class="text-center">{{ idc.id }}</td> <td class="text-center">
<input type="checkbox" name="checked" value="{{ idc.id }}">
</td>
<td class="text-center">{{ idc.name }}</td> <td class="text-center">{{ idc.name }}</td>
<td class="text-center">{{ idc.assets.count }}</td> <td class="text-center">{{ idc.assets.count }}</td>
<td class="text-center">{{ idc.bandwidth }}</td> {# <td class="text-center">{{ idc.bandwidth }}</td>#}
<td class="text-center">{{ idc.contact }}</td> <td class="text-center">{{ idc.contact }}</td>
<td class="text-center">{{ idc.phone }}</td> <td class="text-center">{{ idc.phone }}</td>
<td class="text-center">{{ idc.address }}</td> {# <td class="text-center">{{ idc.address }}</td>#}
<td class="text-center"> <td class="text-center">
<a href="{% url 'assets:idc-update' pk=idc.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a> <a href="{% url 'assets:idc-update' pk=idc.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>
<a onclick="objectDelete(this, '{{ idc.name }}', '{% url 'assets:idc-delete' idc.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a> <a onclick="objectDelete(this, '{{ idc.name }}', '{% url 'assets:idc-delete' idc.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>
...@@ -36,35 +41,6 @@ ...@@ -36,35 +41,6 @@
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
//删除提示样式二,可以选用。
function obj_del2(obj,name,url){
//alert(local);
top.$.jBox.confirm("您确定要删除【"+name+"】吗?", "系统提示",function (c, d, e) {
if (c == "ok") {
//loading("正在提交,请稍等...");
$.ajax({
type : "post",
url : url,
data : {
// idc_id : idc_id
},
success : function(data) {
// alert('删除成功!')
$(obj).parent().parent().remove();
},
dataType : "text"
});
}
}, {buttonsFocus: 1,
draggable: false,
showClose: false});
top.$(".jbox-body .jbox-icon").css("top", "35px");
top.$(".jbox-button-panel").css("height", "35px");
return false
}
</script> </script>
{% endblock %} {% endblock %}
...@@ -9,7 +9,7 @@ from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateVi ...@@ -9,7 +9,7 @@ from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateVi
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.detail import DetailView, SingleObjectMixin from django.views.generic.detail import DetailView, SingleObjectMixin
from django.shortcuts import get_object_or_404, reverse, redirect
from .models import Asset, AssetGroup, IDC, AssetExtend, AdminUser, SystemUser, Label from .models import Asset, AssetGroup, IDC, AssetExtend, AdminUser, SystemUser, Label
from .forms import AssetForm, AssetGroupForm, IDCForm, AdminUserForm, SystemUserForm from .forms import AssetForm, AssetGroupForm, IDCForm, AdminUserForm, SystemUserForm
from .hands import AdminUserRequiredMixin from .hands import AdminUserRequiredMixin
...@@ -70,15 +70,21 @@ class AssetGroupCreateView(AdminUserRequiredMixin, CreateView): ...@@ -70,15 +70,21 @@ class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
'app': _('Assets'), 'app': _('Assets'),
'action': _('Create asset group'), 'action': _('Create asset group'),
'assets': Asset.objects.all(), 'assets': Asset.objects.all(),
# 'systemusers':SystemUser.objects.all(),
} }
kwargs.update(context) kwargs.update(context)
return super(AssetGroupCreateView, self).get_context_data(**kwargs) return super(AssetGroupCreateView, self).get_context_data(**kwargs)
def form_valid(self, form): def form_valid(self, form):
print(form.data) asset_group = form.save()
assets_id_list = self.request.POST.getlist('assets', [])
assets = [get_object_or_404(Asset, id=asset_id) for asset_id in assets_id_list]
asset_group.created_by = self.request.user.username or 'Admin'
asset_group.assets.add(*tuple(assets))
asset_group.save()
return super(AssetGroupCreateView, self).form_valid(form) return super(AssetGroupCreateView, self).form_valid(form)
class AssetGroupListView(AdminUserRequiredMixin, ListView): class AssetGroupListView(AdminUserRequiredMixin, ListView):
model = AssetGroup model = AssetGroup
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
...@@ -129,6 +135,7 @@ class AssetGroupDetailView(SingleObjectMixin, AdminUserRequiredMixin, ListView): ...@@ -129,6 +135,7 @@ class AssetGroupDetailView(SingleObjectMixin, AdminUserRequiredMixin, ListView):
return super(AssetGroupDetailView, self).get_context_data(**kwargs) return super(AssetGroupDetailView, self).get_context_data(**kwargs)
class AssetGroupUpdateView(AdminUserRequiredMixin, UpdateView): class AssetGroupUpdateView(AdminUserRequiredMixin, UpdateView):
model = AssetGroup model = AssetGroup
form_class = AssetGroupForm form_class = AssetGroupForm
...@@ -188,12 +195,18 @@ class IDCCreateView(AdminUserRequiredMixin, CreateView): ...@@ -188,12 +195,18 @@ class IDCCreateView(AdminUserRequiredMixin, CreateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
'app': 'assets', 'app': _('assets'),
'action': 'Create IDC' 'action': _('Create IDC'),
} }
kwargs.update(context) kwargs.update(context)
return super(IDCCreateView, self).get_context_data(**kwargs) return super(IDCCreateView, self).get_context_data(**kwargs)
def form_valid(self, form):
IDC = form.save(commit=False)
IDC.created_by = self.request.user.username or 'System'
IDC.save()
# IDC_add_success_next(user)
return super(IDCCreateView, self).form_valid(form)
class IDCUpdateView(AdminUserRequiredMixin, UpdateView): class IDCUpdateView(AdminUserRequiredMixin, UpdateView):
model = IDC model = IDC
...@@ -207,6 +220,14 @@ class IDCUpdateView(AdminUserRequiredMixin, UpdateView): ...@@ -207,6 +220,14 @@ class IDCUpdateView(AdminUserRequiredMixin, UpdateView):
idc.save() idc.save()
return super(IDCUpdateView, self).form_valid(form) return super(IDCUpdateView, self).form_valid(form)
def get_context_data(self, **kwargs):
context = {
'app': _('assets'),
'action': _('Update IDC'),
}
kwargs.update(context)
return super(IDCUpdateView, self).get_context_data(**kwargs)
class IDCDetailView(AdminUserRequiredMixin, DetailView): class IDCDetailView(AdminUserRequiredMixin, DetailView):
pass pass
......
...@@ -297,6 +297,15 @@ SESSION_ENGINE = 'redis_sessions.session' ...@@ -297,6 +297,15 @@ SESSION_ENGINE = 'redis_sessions.session'
SESSION_REDIS_PREFIX = 'session' SESSION_REDIS_PREFIX = 'session'
SESSION_REDIS_HOST = CONFIG.REDIS_HOST
SESSION_REDIS_PORT = CONFIG.REDIS_PORT
SESSION_REDIS_PASSWORD = CONFIG.REDIS_PASSWORD
SESSION_REDIS_DB = CONFIG.REDIS_DB
# Custom User Auth model # Custom User Auth model
AUTH_USER_MODEL = 'users.User' AUTH_USER_MODEL = 'users.User'
...@@ -306,7 +315,6 @@ BROKER_URL = 'redis://%(password)s%(host)s:%(port)s/3' % { ...@@ -306,7 +315,6 @@ BROKER_URL = 'redis://%(password)s%(host)s:%(port)s/3' % {
'host': CONFIG.REDIS_HOST or '127.0.0.1', 'host': CONFIG.REDIS_HOST or '127.0.0.1',
'port': CONFIG.REDIS_PORT or 6379, 'port': CONFIG.REDIS_PORT or 6379,
} }
CELERY_RESULT_BACKEND = BROKER_URL CELERY_RESULT_BACKEND = BROKER_URL
# Captcha settings, more see https://django-simple-captcha.readthedocs.io/en/latest/advanced.html # Captcha settings, more see https://django-simple-captcha.readthedocs.io/en/latest/advanced.html
...@@ -314,5 +322,4 @@ CAPTCHA_IMAGE_SIZE = (75, 33) ...@@ -314,5 +322,4 @@ CAPTCHA_IMAGE_SIZE = (75, 33)
CAPTCHA_FOREGROUND_COLOR = '#001100' CAPTCHA_FOREGROUND_COLOR = '#001100'
# #
SESSION_COOKIE_AGE = 10800 # 3 hours
SESSION_SAVE_EVERY_REQUEST = True
/*
@import url("https://fonts.useso.com/css?family=Open+Sans:300,400,600,700"); @import url("https://fonts.useso.com/css?family=Open+Sans:300,400,600,700");
@import url("https://fonts.useso.com/css?family=Roboto:400,300,500,700"); @import url("https://fonts.useso.com/css?family=Roboto:400,300,500,700");
/* /*
......
[.ShellClassInfo]
IconFile=%SystemRoot%\system32\SHELL32.dll
IconIndex=161
@charset "utf-8";
/*
提示:CSS 样式只允许修改颜色属性,或图片的地址(图片大小要和默认的一致)。border:dotted solid double dashed
*/
*:focus {outline: none;}
/* fade */
.jbox-fade{background-color:#000000;}
/* drag */
.jbox-drag{border:1px dashed #003870;}
/* jbox */
div.jbox {padding:0px;border:none;font-size:12px;}
/* border */
div.jbox .jbox-border{background: none repeat scroll 0 0 #000000;filter:alpha(opacity=20);-moz-opacity:0.2;opacity:0.2;}
/* container */
div.jbox .jbox-container{background-color:#ffffff;border:1px solid #999999;}
/* title-panel */
div.jbox .jbox-title-panel{background:#2f4050;border-bottom:1px solid #CCCCCC;}
div.jbox .jbox-title{font-weight:bold;color:#ffffff;}
div.jbox .jbox-title-icon{background:url(images/jbox-title-icon.gif) no-repeat scroll 3px 5px transparent;}
div.jbox .jbox-close,div.jbox .jbox-close-hover{background:url(images/jbox-close1.gif) no-repeat scroll 0px 0px transparent;}
div.jbox .jbox-close-hover{background-position:-16px 0;}
/* content */
div.jbox .jbox-content{min-height:24px;line-height:18px;color:#444444;}
div.jbox .jbox-content-loading{background-color:#E6E6E6;}
div.jbox .jbox-content-loading-image{background:url(images/jbox-content-loading.gif) no-repeat bottom center;}
/* button-panel */
div.jbox .jbox-button-panel{border-top:1px solid #CCCCCC;background-color: #EEEEEE;}
div.jbox .jbox-bottom-text{text-indent:10px;color:#444444;}
div.jbox .jbox-button{background:url(images/jbox-button2.png) repeat-x transparent;border:#AAAAAA 1px solid;color:#888888;border-radius:3px 3px 3px 3px;margin:1px 7px 0px 0px;height:22px;cursor:default;}
div.jbox .jbox-button-hover{background-position:0px -20px;color:#666666;}
div.jbox .jbox-button-active{background-position:0px -40px;}
div.jbox-warning .jbox .jbox-button-panel{background-color: #FFFFFF;}
/* tip-color */
div.jbox .jbox-tip-color{background-color:#003870;border-color:#003870;border-radius:3px 3px 3px 3px;color:#ffffff;}
/* icons */
div.jbox span.jbox-icon{background:url(images/jbox-icons.png) no-repeat scroll 0 0 transparent;_background:url(images/jbox-icons-ie6.gif) no-repeat scroll 0 0 transparent;}
div.jbox span.jbox-icon-info {background-position:0 0;}
div.jbox span.jbox-icon-question {background-position:-36px 0;}
div.jbox span.jbox-icon-success {background-position:-72px 0;}
div.jbox span.jbox-icon-warning {background-position:-108px 0;}
div.jbox span.jbox-icon-error {background-position:-144px 0;}
div.jbox span.jbox-icon-none {display: none; overflow:hidden;}
div.jbox span.jbox-icon-loading {background:url(images/jbox-loading1.gif) no-repeat scroll 0 0 transparent;}
\ No newline at end of file
[.ShellClassInfo]
IconFile=%SystemRoot%\system32\SHELL32.dll
IconIndex=161
@charset "utf-8";
*:focus {outline: none;}
/* fade */
.jbox-fade{background-color:#000000;}
/* drag */
.jbox-drag{border:1px dashed #0097d4;}
/* jbox */
div.jbox {padding:0px;border:none;font-size:12px;}
/* border */
div.jbox .jbox-border{background: none repeat scroll 0 0 #000000;filter:alpha(opacity=20);-moz-opacity:0.2;opacity:0.2;}
/* container */
div.jbox .jbox-container{background-color:#ffffff;border:1px solid #999999;}
/* title-panel */
div.jbox .jbox-title-panel{background: #2f4050;background: -webkit-gradient(linear, left top, left bottom, from(#2f4050), to(#2f4050));background: -moz-linear-gradient(top, #2f4050, #2f4050);filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#2f4050', endColorstr='#2f4050');border-bottom:1px solid #999999;}
div.jbox .jbox-title{font-weight:bold;color:#ffffff;}
div.jbox .jbox-title-icon{background:url(images/jbox-title-icon.gif) no-repeat scroll 3px 5px transparent;}
div.jbox .jbox-close,div.jbox .jbox-close-hover{background:url(images/jbox-close1.gif) no-repeat scroll 0px 0px transparent;}
div.jbox .jbox-close-hover{background-position:-16px 0;}
/* content */
div.jbox .jbox-content{min-height:24px;line-height:18px;color:#444444;}
div.jbox .jbox-content-loading{background-color:#E6E6E6;}
div.jbox .jbox-content-loading-image{background:url(images/jbox-content-loading.gif) no-repeat bottom center;}
/* button-panel */
div.jbox .jbox-button-panel{border-top:1px solid #CCCCCC;background-color: #EEEEEE;}
div.jbox .jbox-bottom-text{text-indent:10px;color:#444444;}
div.jbox .jbox-button{background: #0097d4;background: -webkit-gradient(linear, left top, left bottom, from(#2f4050), to(#2f4050));background: -moz-linear-gradient(top, #2f4050, #2f4050);filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#2f4050', endColorstr='#2f4050');border:#004b6a 1px solid;color:#fff;border-radius:3px 3px 3px 3px;margin:1px 7px 0px 0px;height:22px;cursor:default;}
div.jbox .jbox-button-hover{background: #0097d4;background: -webkit-gradient(linear, left top, left bottom, from(#0097d4), to(#005b7f));background: -moz-linear-gradient(top, #0097d4, #005b7f);filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0097d4', endColorstr='#005b7f');}
div.jbox .jbox-button-active{background: -webkit-gradient(linear, left top, left bottom, from(#005b7f), to(#0097d4));background: -moz-linear-gradient(top, #005b7f, #0097d4);filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#005b7f', endColorstr='#0097d4');}
div.jbox-warning .jbox .jbox-button-panel{background-color: #FFFFFF;}
/* tip-color */
div.jbox .jbox-tip-color{background: #0097d4;background: -webkit-gradient(linear, left top, left bottom, from(#0097d4), to(#005b7f));background: -moz-linear-gradient(top, #0097d4, #005b7f);filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0097d4', endColorstr='#005b7f');border-color:#004b6a;border-radius:3px 3px 3px 3px;color:#fff;}
/* icons */
div.jbox span.jbox-icon{background:url(images/jbox-icons.png) no-repeat scroll 0 0 transparent;_background:url(images/jbox-icons-ie6.gif) no-repeat scroll 0 0 transparent;}
div.jbox span.jbox-icon-info {background-position:0 0;}
div.jbox span.jbox-icon-question {background-position:-36px 0;}
div.jbox span.jbox-icon-success {background-position:-72px 0;}
div.jbox span.jbox-icon-warning {background-position:-108px 0;}
div.jbox span.jbox-icon-error {background-position:-144px 0;}
div.jbox span.jbox-icon-none {display: none; overflow:hidden;}
div.jbox span.jbox-icon-loading {background:url(images/jbox-loading1.gif) no-repeat scroll 0 0 transparent;}
\ No newline at end of file

/* jBox 全局设置 */
var jBoxConfig = {};
jBoxConfig.defaults = {
id: null, /* 在页面中的唯一id,如果为null则自动生成随机id,一个id只会显示一个jBox */
top: '15%', /* 窗口离顶部的距离,可以是百分比或像素(如 '100px') */
border: 5, /* 窗口的外边框像素大小,必须是0以上的整数 */
opacity: 0.1, /* 窗口隔离层的透明度,如果设置为0,则不显示隔离层 */
timeout: 0, /* 窗口显示多少毫秒后自动关闭,如果设置为0,则不自动关闭 */
showType: 'fade', /* 窗口显示的类型,可选值有:show、fade、slide */
showSpeed: 'fast', /* 窗口显示的速度,可选值有:'slow'、'fast'、表示毫秒的整数 */
showIcon: true, /* 是否显示窗口标题的图标,true显示,false不显示,或自定义的CSS样式类名(以为图标为背景) */
showClose: true, /* 是否显示窗口右上角的关闭按钮 */
draggable: true, /* 是否可以拖动窗口 */
dragLimit: true, /* 在可以拖动窗口的情况下,是否限制在可视范围 */
dragClone: false, /* 在可以拖动窗口的情况下,鼠标按下时窗口是否克隆窗口 */
persistent: true, /* 在显示隔离层的情况下,点击隔离层时,是否坚持窗口不关闭 */
showScrolling: true, /* 是否显示浏览的滚动条 */
ajaxData: {}, /* 在窗口内容使用get:或post:前缀标识的情况下,ajax post的数据,例如:{ id: 1 } 或 "id=1" */
iframeScrolling: 'auto', /* 在窗口内容使用iframe:前缀标识的情况下,iframe的scrolling属性值,可选值有:'auto'、'yes'、'no' */
title: 'jBox', /* 窗口的标题 */
width: 350, /* 窗口的宽度,值为'auto'或表示像素的整数 */
height: 'auto', /* 窗口的高度,值为'auto'或表示像素的整数 */
bottomText: '', /* 窗口的按钮左边的内容,当没有按钮时此设置无效 */
buttons: { '确定': 'ok' }, /* 窗口的按钮 */
buttonsFocus: 0, /* 表示第几个按钮为默认按钮,索引从0开始 */
loaded: function (h) { }, /* 窗口加载完成后执行的函数,需要注意的是,如果是ajax或iframe也是要等加载完http请求才算窗口加载完成,参数h表示窗口内容的jQuery对象 */
submit: function (v, h, f) { return true; }, /* 点击窗口按钮后的回调函数,返回true时表示关闭窗口,参数有三个,v表示所点的按钮的返回值,h表示窗口内容的jQuery对象,f表示窗口内容里的form表单键值 */
closed: function () { } /* 窗口关闭后执行的函数 */
};
jBoxConfig.stateDefaults = {
content: '', /* 状态的内容,不支持前缀标识 */
buttons: { '确定': 'ok' }, /* 状态的按钮 */
buttonsFocus: 0, /* 表示第几个按钮为默认按钮,索引从0开始 */
submit: function (v, h, f) { return true; } /* 点击状态按钮后的回调函数,返回true时表示关闭窗口,参数有三个,v表示所点的按钮的返回值,h表示窗口内容的jQuery对象,f表示窗口内容里的form表单键值 */
};
jBoxConfig.tipDefaults = {
content: '', /* 提示的内容,不支持前缀标识 */
icon: 'info', /* 提示的图标,可选值有'info'、'success'、'warning'、'error'、'loading',默认值为'info',当为'loading'时,timeout值会被设置为0,表示不会自动关闭。 */
top: '40%', /* 提示离顶部的距离,可以是百分比或像素(如 '100px') */
width: 'auto', /* 提示的高度,值为'auto'或表示像素的整数 */
height: 'auto', /* 提示的高度,值为'auto'或表示像素的整数 */
opacity: 0, /* 窗口隔离层的透明度,如果设置为0,则不显示隔离层 */
timeout: 3000, /* 提示显示多少毫秒后自动关闭,必须是大于0的整数 */
closed: function () { } /* 提示关闭后执行的函数 */
};
jBoxConfig.messagerDefaults = {
content: '', /* 信息的内容,不支持前缀标识 */
title: 'jBox', /* 信息的标题 */
icon: 'none', /* 信息图标,值为'none'时为不显示图标,可选值有'none'、'info'、'question'、'success'、'warning'、'error' */
width: 350, /* 信息的高度,值为'auto'或表示像素的整数 */
height: 'auto', /* 信息的高度,值为'auto'或表示像素的整数 */
timeout: 3000, /* 信息显示多少毫秒后自动关闭,如果设置为0,则不自动关闭 */
showType: 'slide', /* 信息显示的类型,可选值有:show、fade、slide */
showSpeed: 600, /* 信息显示的速度,可选值有:'slow'、'fast'、表示毫秒的整数 */
border: 0, /* 信息的外边框像素大小,必须是0以上的整数 */
buttons: {}, /* 信息的按钮 */
buttonsFocus: 0, /* 表示第几个按钮为默认按钮,索引从0开始 */
loaded: function (h) { }, /* 窗口加载完成后执行的函数,参数h表示窗口内容的jQuery对象 */
submit: function (v, h, f) { return true; }, /* 点击信息按钮后的回调函数,返回true时表示关闭窗口,参数有三个,v表示所点的按钮的返回值,h表示窗口内容的jQuery对象,f表示窗口内容里的form表单键值 */
closed: function () { } /* 信息关闭后执行的函数 */
};
jBoxConfig.languageDefaults = {
close: '关闭', /* 窗口右上角关闭按钮提示 */
ok: '确定', /* $.jBox.prompt() 系列方法的“确定”按钮文字 */
yes: '是', /* $.jBox.warning() 方法的“是”按钮文字 */
no: '否', /* $.jBox.warning() 方法的“否”按钮文字 */
cancel: '取消' /* $.jBox.confirm() 和 $.jBox.warning() 方法的“取消”按钮文字 */
};
$.jBox.setDefaults(jBoxConfig);
/*!
* jQuery Migrate - v1.1.1 - 2013-02-16
* https://github.com/jquery/jquery-migrate
* Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; Licensed MIT
*/
(function(s,p,i){var D={};s.migrateWarnings=[];if(!s.migrateMute&&p.console&&console.log){console.log("JQMIGRATE: Logging is active")}if(s.migrateTrace===i){s.migrateTrace=true}s.migrateReset=function(){D={};s.migrateWarnings.length=0};function h(G){if(!D[G]){D[G]=true;s.migrateWarnings.push(G);if(p.console&&console.warn&&!s.migrateMute){console.warn("JQMIGRATE: "+G);if(s.migrateTrace&&console.trace){console.trace()}}}}function a(I,K,H,J){if(Object.defineProperty){try{Object.defineProperty(I,K,{configurable:true,enumerable:true,get:function(){h(J);return H},set:function(L){h(J);H=L}});return}catch(G){}}s._definePropertyBroken=true;I[K]=H}if(document.compatMode==="BackCompat"){h("jQuery is not compatible with Quirks Mode")}var f=s("<input/>",{size:1}).attr("size")&&s.attrFn,x=s.attr,w=s.attrHooks.value&&s.attrHooks.value.get||function(){return null},j=s.attrHooks.value&&s.attrHooks.value.set||function(){return i},t=/^(?:input|button)$/i,y=/^[238]$/,B=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,k=/^(?:checked|selected)$/i;a(s,"attrFn",f||{},"jQuery.attrFn is deprecated");s.attr=function(K,I,L,J){var H=I.toLowerCase(),G=K&&K.nodeType;if(J){if(x.length<4){h("jQuery.fn.attr( props, pass ) is deprecated")}if(K&&!y.test(G)&&(f?I in f:s.isFunction(s.fn[I]))){return s(K)[I](L)}}if(I==="type"&&L!==i&&t.test(K.nodeName)&&K.parentNode){h("Can't change the 'type' of an input or button in IE 6/7/8")}if(!s.attrHooks[H]&&B.test(H)){s.attrHooks[H]={get:function(N,M){var P,O=s.prop(N,M);return O===true||typeof O!=="boolean"&&(P=N.getAttributeNode(M))&&P.nodeValue!==false?M.toLowerCase():i},set:function(N,P,M){var O;if(P===false){s.removeAttr(N,M)}else{O=s.propFix[M]||M;if(O in N){N[O]=true}N.setAttribute(M,M.toLowerCase())}return M}};if(k.test(H)){h("jQuery.fn.attr('"+H+"') may use property instead of attribute")
}}return x.call(s,K,I,L)};s.attrHooks.value={get:function(H,G){var I=(H.nodeName||"").toLowerCase();if(I==="button"){return w.apply(this,arguments)}if(I!=="input"&&I!=="option"){h("jQuery.fn.attr('value') no longer gets properties")}return G in H?H.value:null},set:function(G,H){var I=(G.nodeName||"").toLowerCase();if(I==="button"){return j.apply(this,arguments)}if(I!=="input"&&I!=="option"){h("jQuery.fn.attr('value', val) no longer sets properties")}G.value=H}};var q,E,z=s.fn.init,A=s.parseJSON,v=/^(?:[^<]*(<[\w\W]+>)[^>]*|#([\w\-]*))$/;s.fn.init=function(G,J,I){var H;if(G&&typeof G==="string"&&!s.isPlainObject(J)&&(H=v.exec(G))&&H[1]){if(G.charAt(0)!=="<"){h("$(html) HTML strings must start with '<' character")}if(J&&J.context){J=J.context}if(s.parseHTML){return z.call(this,s.parseHTML(s.trim(G),J,true),J,I)}}return z.apply(this,arguments)};s.fn.init.prototype=s.fn;s.parseJSON=function(G){if(!G&&G!==null){h("jQuery.parseJSON requires a valid JSON string");return null}return A.apply(this,arguments)};s.uaMatch=function(H){H=H.toLowerCase();var G=/(chrome)[ \/]([\w.]+)/.exec(H)||/(webkit)[ \/]([\w.]+)/.exec(H)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(H)||/(msie) ([\w.]+)/.exec(H)||H.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(H)||[];return{browser:G[1]||"",version:G[2]||"0"}};if(!s.browser){q=s.uaMatch(navigator.userAgent);E={};if(q.browser){E[q.browser]=true;E.version=q.version}if(E.chrome){E.webkit=true}else{if(E.webkit){E.safari=true}}s.browser=E}a(s,"browser",s.browser,"jQuery.browser is deprecated");s.sub=function(){function G(J,K){return new G.fn.init(J,K)}s.extend(true,G,this);G.superclass=this;G.fn=G.prototype=this();G.fn.constructor=G;G.sub=this.sub;G.fn.init=function I(J,K){if(K&&K instanceof s&&!(K instanceof G)){K=G(K)}return s.fn.init.call(this,J,K,H)};G.fn.init.prototype=G.fn;var H=G(document);h("jQuery.sub() is deprecated");return G};s.ajaxSetup({converters:{"text json":s.parseJSON}});var n=s.fn.data;s.fn.data=function(I){var H,G,J=this[0];if(J&&I==="events"&&arguments.length===1){H=s.data(J,I);
G=s._data(J,I);if((H===i||H===G)&&G!==i){h("Use of jQuery.fn.data('events') is deprecated");return G}}return n.apply(this,arguments)};var o=/\/(java|ecma)script/i,u=s.fn.andSelf||s.fn.addBack;s.fn.andSelf=function(){h("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()");return u.apply(this,arguments)};if(!s.clean){s.clean=function(G,H,N,J){H=H||document;H=!H.nodeType&&H[0]||H;H=H.ownerDocument||H;h("jQuery.clean() is deprecated");var K,I,L,O,M=[];s.merge(M,s.buildFragment(G,H).childNodes);if(N){L=function(P){if(!P.type||o.test(P.type)){return J?J.push(P.parentNode?P.parentNode.removeChild(P):P):N.appendChild(P)}};for(K=0;(I=M[K])!=null;K++){if(!(s.nodeName(I,"script")&&L(I))){N.appendChild(I);if(typeof I.getElementsByTagName!=="undefined"){O=s.grep(s.merge([],I.getElementsByTagName("script")),L);M.splice.apply(M,[K+1,0].concat(O));K+=O.length}}}}return M}}var c=s.event.add,b=s.event.remove,g=s.event.trigger,r=s.fn.toggle,d=s.fn.live,m=s.fn.die,C="ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",e=new RegExp("\\b(?:"+C+")\\b"),F=/(?:^|\s)hover(\.\S+|)\b/,l=function(G){if(typeof(G)!=="string"||s.event.special.hover){return G}if(F.test(G)){h("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'")}return G&&G.replace(F,"mouseenter$1 mouseleave$1")};if(s.event.props&&s.event.props[0]!=="attrChange"){s.event.props.unshift("attrChange","attrName","relatedNode","srcElement")}if(s.event.dispatch){a(s.event,"handle",s.event.dispatch,"jQuery.event.handle is undocumented and deprecated")}s.event.add=function(J,H,I,K,G){if(J!==document&&e.test(H)){h("AJAX events should be attached to document: "+H)}c.call(this,J,l(H||""),I,K,G)};s.event.remove=function(K,I,J,G,H){b.call(this,K,l(I)||"",J,G,H)};s.fn.error=function(){var G=Array.prototype.slice.call(arguments,0);h("jQuery.fn.error() is deprecated");G.splice(0,0,"error");if(arguments.length){return this.bind.apply(this,G)}this.triggerHandler.apply(this,G);return this};s.fn.toggle=function(K,I){if(!s.isFunction(K)||!s.isFunction(I)){return r.apply(this,arguments)
}h("jQuery.fn.toggle(handler, handler...) is deprecated");var H=arguments,G=K.guid||s.guid++,J=0,L=function(M){var N=(s._data(this,"lastToggle"+K.guid)||0)%J;s._data(this,"lastToggle"+K.guid,N+1);M.preventDefault();return H[N].apply(this,arguments)||false};L.guid=G;while(J<H.length){H[J++].guid=G}return this.click(L)};s.fn.live=function(G,I,H){h("jQuery.fn.live() is deprecated");if(d){return d.apply(this,arguments)}s(this.context).on(G,this.selector,I,H);return this};s.fn.die=function(G,H){h("jQuery.fn.die() is deprecated");if(m){return m.apply(this,arguments)}s(this.context).off(G,this.selector||"**",H);return this};s.event.trigger=function(I,J,H,G){if(!H&&!e.test(I)){h("Global events are undocumented and deprecated")}return g.call(this,I,J,H||document,G)};s.each(C.split("|"),function(H,G){s.event.special[G]={setup:function(){var I=this;if(I!==document){s.event.add(document,G+"."+s.guid,function(){s.event.trigger(G,null,I,true)});s._data(this,G,s.guid++)}return false},teardown:function(){if(this!==document){s.event.remove(document,G+"."+s._data(this,G))}return false}}})})(jQuery,window);
\ No newline at end of file
This diff is collapsed.
...@@ -13,11 +13,6 @@ ...@@ -13,11 +13,6 @@
<!-- scripts --> <!-- scripts -->
<script src="{% static 'js/jquery-2.1.1.js' %}"></script> <script src="{% static 'js/jquery-2.1.1.js' %}"></script>
<!-- Jbox -->
<link href="{% static 'jbox/Skins2/jumpserver/jbox.css' %}" rel="stylesheet">
<script src="{% static 'jbox/jquery-migrate-1.1.1.min.js' %}"></script>
<script src="{% static 'jbox/jquery.jBox-2.3.min.js' %}"></script>
<script src="{% static 'jbox/i18n/jquery.jBox-zh-CN.js' %}"></script>
<!-- Sweet alert --> <!-- Sweet alert -->
<script src="{% static 'js/plugins/sweetalert/sweetalert.min.js' %}"></script> <script src="{% static 'js/plugins/sweetalert/sweetalert.min.js' %}"></script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment