Commit ce5950ca authored by ibuler's avatar ibuler

Merge with asset

parents 65461a09 24e31a69
# coding:utf-8
from django import forms
from .models import IDC, Asset, AssetGroup, AdminUser, SystemUser
from .models import IDC, Asset, AssetGroup, AdminUser, SystemUser, Tag
from django.utils.translation import gettext_lazy as _
class AssetForm(forms.ModelForm):
# class AssetForm(forms.ModelForm):
# class Meta:
# model = Asset
#
# fields = [
# 'ip', 'other_ip', 'remote_card_ip', 'hostname', 'port', 'groups', 'username', 'password',
# 'idc', 'mac_address', 'brand', 'cpu', 'memory', 'disk', 'os', 'cabinet_no', 'cabinet_pos',
# 'number', 'status', 'type', 'env', 'sn', 'is_active', 'comment', 'admin_user', 'system_users'
# ]
#
# widgets = {
# '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')}),
# 'admin_user': forms.SelectMultiple(attrs={'class': 'select2-admin-user', 'data-placeholder': _('Select asset admin user')}),
# }
#
class AssetCreateForm(forms.ModelForm):
tags = forms.CharField(label=_('Tags'), widget=forms.TextInput(attrs={'id': 'tags'}),
required=False, help_text='Use `,` split')
def __init__(self, *args, **kwargs):
instance = kwargs.get('instance', None)
if instance:
initial = kwargs.get('initial', {})
tags = instance.tags.all()
initial['tags'] = ",".join([tag.value for tag in tags])
print(kwargs.get('initial'))
super(AssetCreateForm, self).__init__(*args, **kwargs)
def _save_m2m(self):
tags = self.cleaned_data['tags']
if tags:
value_list = tags.split(',')
self.instance.tags.all().delete()
Tag.objects.bulk_create(
[Tag(value=value, asset=self.instance) for value in value_list]
)
class Meta:
model = Asset
fields = [
"ip", "other_ip", "remote_card_ip", "hostname", "port", "groups", "username", "password",
"idc", "mac_address", "brand", "cpu", "memory", "disk", "os", "cabinet_no", "cabinet_pos",
"number", "status", "type", "env", "sn", "is_active", "comment", "admin_user", "system_users"
'hostname', 'ip', 'port', 'type', 'comment', 'admin_user', 'system_users', 'idc', 'groups',
'other_ip', 'remote_card_ip', 'mac_address', 'brand', 'cpu', 'memory', 'disk', 'os', 'cabinet_no',
'cabinet_pos', 'number', 'status', 'env', 'sn',
]
widgets = {
'groups': forms.SelectMultiple(attrs={'class': 'select2-groups', 'data-placeholder': _('Select asset groups')}),
'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')}),
'groups': forms.SelectMultiple(attrs={'class': 'select2',
'data-placeholder': _('Select asset groups')}),
'system_users': forms.SelectMultiple(attrs={'class': 'select2',
'data-placeholder': _('Select asset system users')}),
'admin_user': forms.Select(attrs={'class': 'select2', 'data-placeholder': _('Select asset admin user')}),
}
help_texts = {
'hostname': '* required',
'ip': '* required',
}
......@@ -32,7 +77,7 @@ class AssetGroupForm(forms.ModelForm):
)
def __init__(self, *args, **kwargs):
if kwargs.get('instance'):
if kwargs.get('instance', None):
initial = kwargs.get('initial', {})
initial['assets'] = kwargs['instance'].assets.all()
super(AssetGroupForm, self).__init__(*args, **kwargs)
......
# coding:utf-8
from __future__ import unicode_literals, absolute_import
import functools
from django.db import models
import logging
from django.utils.translation import ugettext_lazy as _
......@@ -26,6 +27,10 @@ class IDC(models.Model):
def __unicode__(self):
return self.name
@classmethod
def initial(cls):
return cls.objects.get_or_create(name=_('Default'), created_by=_('System'), comment=_('Default IDC'))[0]
class Meta:
db_table = 'idc'
......@@ -55,10 +60,10 @@ class IDC(models.Model):
class AssetExtend(models.Model):
key = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('KEY'))
value = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('VALUE'))
key = models.CharField(max_length=64, verbose_name=_('KEY'))
value = models.CharField(max_length=64, verbose_name=_('VALUE'))
created_by = models.CharField(max_length=32, blank=True, verbose_name=_("Created by"))
date_created = models.DateTimeField(auto_now=True, null=True, blank=True)
date_created = models.DateTimeField(auto_now=True, null=True)
comment = models.TextField(blank=True, verbose_name=_('Comment'))
def __unicode__(self):
......@@ -83,6 +88,7 @@ class AssetExtend(models.Model):
class Meta:
db_table = 'asset_extend'
unique_together = ('key', 'value')
class AdminUser(models.Model):
......@@ -249,7 +255,7 @@ class AssetGroup(models.Model):
@classmethod
def initial(cls):
asset_group = cls(name=_('Default'), commont=_('Default asset group'))
asset_group = cls(name=_('Default'), comment=_('Default asset group'))
asset_group.save()
@classmethod
......@@ -271,19 +277,30 @@ class AssetGroup(models.Model):
continue
def get_default_extend(key, value):
try:
return AssetExtend.objects.get_or_create(key=key, value=value)[0]
except:
return None
def get_default_idc():
return IDC.initial()
class Asset(models.Model):
ip = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('IP'))
ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'))
other_ip = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('Other IP'))
remote_card_ip = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Remote card IP'))
hostname = models.CharField(max_length=128, unique=True, null=True, blank=True, verbose_name=_('Hostname'))
port = models.IntegerField(default=22, null=True, blank=True, verbose_name=_('Port'))
hostname = models.CharField(max_length=128, blank=True, verbose_name=_('Hostname'))
port = models.IntegerField(default=22, verbose_name=_('Port'))
groups = models.ManyToManyField(AssetGroup, blank=True, related_name='assets', verbose_name=_('Asset groups'))
username = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Admin user'))
password = models.CharField(max_length=256, null=True, blank=True, verbose_name=_("Admin password"))
admin_user = models.ForeignKey(AdminUser, null=True, blank=True, related_name='assets',
on_delete=models.SET_NULL, verbose_name=_("Admin user"))
system_users = models.ManyToManyField(SystemUser, blank=True, related_name='assets', verbose_name=_("System User"))
idc = models.ForeignKey(IDC, null=True, related_name='assets', on_delete=models.SET_NULL, verbose_name=_('IDC'))
idc = models.ForeignKey(IDC, null=True, related_name='assets',
on_delete=models.SET_NULL, verbose_name=_('IDC'),)
# default=get_default_idc)
mac_address = models.CharField(max_length=20, null=True, blank=True, verbose_name=_("Mac address"))
brand = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('Brand'))
cpu = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('CPU'))
......@@ -293,27 +310,35 @@ class Asset(models.Model):
cabinet_no = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Cabinet number'))
cabinet_pos = models.IntegerField(null=True, blank=True, verbose_name=_('Cabinet position'))
number = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Asset number'))
status = models.ForeignKey(AssetExtend, null=True, blank=True, related_name="asset_status_extend",
verbose_name=_('Asset status'))
type = models.ForeignKey(AssetExtend, null=True, blank=True, related_name="asset_type_extend",
verbose_name=_('Asset type'))
env = models.ForeignKey(AssetExtend, null=True, blank=True, related_name="asset_env_extend",
verbose_name=_('Asset environment'))
status = models.ForeignKey(AssetExtend, null=True, blank=True,
related_name="status_asset", verbose_name=_('Asset status'),)
# default=functools.partial(get_default_extend, 'status', 'In use'))
type = models.ForeignKey(AssetExtend, null=True, limit_choices_to={'key': 'type'},
related_name="type_asset", verbose_name=_('Asset type'),)
# default=functools.partial(get_default_extend, 'type','Server'))
env = models.ForeignKey(AssetExtend, blank=True, null=True, limit_choices_to={'key': 'env'},
related_name="env_asset", verbose_name=_('Asset environment'),)
# default=functools.partial(get_default_extend, 'env', 'Production'))
sn = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Serial number'))
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
date_created = models.DateTimeField(auto_now=True, null=True, blank=True, verbose_name=_('Date added'))
comment = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Comment'))
comment = models.TextField(max_length=128, null=True, blank=True, verbose_name=_('Comment'))
def __unicode__(self):
return '%(ip)s:%(port)s' % {'ip': self.ip, 'port': self.port}
def initial(self):
pass
def is_valid(self):
warning = ''
if not self.is_active:
warning += ' inactive'
else:
return True, ''
return False, warning
class Meta:
db_table = 'asset'
index_together = ('ip', 'port')
unique_together = ('ip', 'port')
@classmethod
def generate_fake(cls, count=100):
......@@ -323,8 +348,8 @@ class Asset(models.Model):
seed()
for i in range(count):
asset = cls(ip='%s.%s.%s.%s' % tuple([forgery_py.forgery.basic.text(length=3, digits=True)
for i in range(0, 4)]),
asset = cls(ip='%s.%s.%s.%s' % (i, i, i, i),
hostname=forgery_py.internet.user_name(True),
admin_user=choice(AdminUser.objects.all()),
idc=choice(IDC.objects.all()),
port=22,
......@@ -339,21 +364,28 @@ class Asset(models.Model):
continue
class Label(models.Model):
key = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('KEY'))
value = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('VALUE'))
asset = models.ForeignKey(Asset, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_('Asset'))
created_by = models.CharField(max_length=32, blank=True, verbose_name=_("Created by"))
date_created = models.DateTimeField(auto_now=True, null=True)
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
class Tag(models.Model):
value = models.CharField(max_length=64, verbose_name=_('VALUE'))
asset = models.ForeignKey(Asset, related_name='tags', on_delete=models.CASCADE, verbose_name=_('Asset'))
def __unicode__(self):
return self.key
return self.value
class Meta:
db_table = 'label'
db_table = 'tag'
unique_together = ('value', 'asset')
def init_all_models():
for cls in (AssetExtend, AssetGroup):
cls.initial()
def generate_fake():
for cls in (AssetGroup, IDC, AdminUser, SystemUser, Asset):
cls.generate_fake()
def flush_all():
for cls in (AssetGroup, AssetExtend, IDC, AdminUser, SystemUser, Asset):
cls.objects.all().delete()
{% extends '_list_base.html' %}
{% extends '_base_list.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
......
{% extends 'base.html' %}
{% extends '_base_create_update.html' %}
{% load static %}
{% load bootstrap %}
{% block custom_head_css_js %}
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-10">
<div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title">
<h5> 添加资产 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
{% load i18n %}
<div class="ibox-content">
<div class="panel blank-panel">
<div class="tab-content">
<form id="assetForm" method="post" class="form-horizontal">
{% block form %}
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
<h3 class="widget-head-color-box">基本信息</h3>
<h3>{% trans 'Basic' %}</h3>
{{ form.hostname|bootstrap_horizontal }}
{{ form.ip|bootstrap_horizontal }}
{{ form.port|bootstrap_horizontal }}
{{ form.type|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>关联资产用户</h3>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">管理用户</label>
<div class="col-sm-9">
<div class="radio i-checks">
<label><input type="radio" checked="checked" id="id_use_default_auth" name="use_default_auth"><span>使用预定义管理用户</span></label>
<label><input type="radio" id="id_use_default_auth" name="use_default_auth"><span>自定义</span></label>
</div>
</div>
</div>
{{ form.admin_user|bootstrap_horizontal }}
<p class="col-sm-offset-2">Tips: 管理用户是服务器存在的root或拥有sudo的用户,用来推送系统用户</p>
<h3>{% trans 'Group' %}</h3>
{{ form.idc|bootstrap_horizontal }}
{{ form.groups|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Asset user' %}</h3>
{{ form.admin_user|bootstrap_horizontal }}
{{ form.system_users|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>所属</h3>
{{ form.idc|bootstrap_horizontal }}
{{ form.groups|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>标签</h3>
<div class="form-group" id="id_label">
<label class="col-sm-2 control-label">Label</label>
<div class="col-sm-4">
<input type="text" placeholder="Key" name="key" class="form-control">
</div>
<div class="col-sm-5">
<input type="text" placeholder="Value" name="value" class="form-control">
</div>
</div>
<div class="col-sm-offset-2">
<i class="fa fa-plus-circle"></i> <span class="nav-label">添加</span><span class="fa arrow"></span>
</div>
<h3>{% trans 'Other' %}</h3>
{{ form.tags|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<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 class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
{% endblock %}
{% block custom_foot_js %}
<script>
$(document).ready(function () {
$('.select2-groups').select2();
$('.select2-admin-user').select2();
$('.select2-system-user').select2();
$('.select2').select2();
$('#tags').inputTags();
})
</script>
{% endblock %}
\ No newline at end of file
{% extends '_list_base.html' %}
{% extends '_base_list.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
......
{% extends '_base_create_update.html' %}
{% load static %}
{% load bootstrap %}
{% load i18n %}
{% block custom_head_css_js_create %}
<link href="{% static "css/plugins/inputTags.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/inputTags.jquery.min.js" %}"></script>
{% endblock %}
{% block form %}
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
<h3>{% trans 'Basic' %}</h3>
{{ form.hostname|bootstrap_horizontal }}
{{ form.ip|bootstrap_horizontal }}
{{ form.port|bootstrap_horizontal }}
{{ form.type|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Group' %}</h3>
{{ form.idc|bootstrap_horizontal }}
{{ form.groups|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Asset user' %}</h3>
{{ form.admin_user|bootstrap_horizontal }}
{{ form.system_users|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Hardware' %}</h3>
{{ form.sn|bootstrap_horizontal }}
{{ form.brand|bootstrap_horizontal }}
{{ form.cpu|bootstrap_horizontal }}
{{ form.memory|bootstrap_horizontal }}
{{ form.disk|bootstrap_horizontal }}
{{ form.mac_address|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Configuration' %}</h3>
{{ form.number|bootstrap_horizontal }}
{{ form.other_ip|bootstrap_horizontal }}
{{ form.remote_card_ip|bootstrap_horizontal }}
{{ form.os|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Location' %}</h3>
{{ form.cabinet_no|bootstrap_horizontal }}
{{ form.cabinet_pos|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Other' %}</h3>
{{ form.status|bootstrap_horizontal }}
{{ form.env|bootstrap_horizontal }}
{{ form.tags|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</form>
{% endblock %}
{% block custom_foot_js %}
<script>
$(document).ready(function () {
$('.select2').select2();
{# $('#tags').inputTags({#}
{# tags: [{% for tag in form.tags.value %} {{ tag|safe }}, {% endfor %}]#}
{# });#}
$('#tags').inputTags(
);
})
</script>
{% endblock %}
\ No newline at end of file
{% extends '_list_base.html' %}
{% extends '_base_list.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
......
{% extends '_list_base.html' %}
{% extends '_base_list.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
......
......@@ -10,45 +10,77 @@ from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin
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 .forms import AssetForm, AssetGroupForm, IDCForm, AdminUserForm, SystemUserForm
from common.utils import int_seq
from .models import Asset, AssetGroup, IDC, AssetExtend, AdminUser, SystemUser, Tag
from .forms import AssetCreateForm, AssetGroupForm, IDCForm, AdminUserForm, SystemUserForm
from .hands import AdminUserRequiredMixin
class AssetListView(AdminUserRequiredMixin, ListView):
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
model = Asset
context_object_name = 'asset_list'
template_name = 'assets/asset_list.html'
def get_queryset(self):
queryset = super(AssetListView, self).get_queryset()
queryset = sorted(queryset, key=self.sorted_by_valid_and_ip)
return queryset
@staticmethod
def sorted_by_valid_and_ip(asset):
ip_list = int_seq(asset.ip.split('.'))
ip_list.insert(0, asset.is_valid()[0])
return ip_list
def get_context_data(self, **kwargs):
context = {
'app': 'Assets',
'action': 'Asset list',
}
kwargs.update(context)
return super(AssetListView, self).get_context_data(**kwargs)
class AssetCreateView(AdminUserRequiredMixin, CreateView):
model = Asset
form_class = AssetForm
form_class = AssetCreateForm
template_name = 'assets/asset_create.html'
success_url = reverse_lazy('assets:asset-list')
def form_valid(self, form):
asset = form.save(commit=False)
key = self.request.POST.get('key', '')
value = self.request.POST.get('value', '')
asset.save()
Label.objects.create(key=key, value=value, asset=asset)
return super(AssetCreateView, self).form_valid(form)
def form_invalid(self, form):
print(form.errors)
return super(AssetCreateView, self).form_invalid(form)
def get_context_data(self, **kwargs):
context = super(AssetCreateView, self).get_context_data(**kwargs)
context.update({'admin_users': AdminUser.objects.all()})
assert isinstance(context, object)
return context
class AssetUpdateView(UpdateView):
pass
context = {
'app': 'Assets',
'action': 'Create asset',
}
kwargs.update(context)
return super(AssetCreateView, self).get_context_data(**kwargs)
class AssetDeleteView(DeleteView):
class AssetUpdateView(AdminUserRequiredMixin, UpdateView):
model = Asset
form_class = AssetCreateForm
template_name = 'assets/asset_update.html'
success_url = reverse_lazy('assets:asset-list')
def get_context_data(self, **kwargs):
context = {
'app': 'Assets',
'action': 'Update asset',
}
kwargs.update(context)
return super(AssetUpdateView, self).get_context_data(**kwargs)
class AssetListView(ListView):
class AssetDeleteView(DeleteView):
model = Asset
context_object_name = 'assets'
template_name = 'assets/asset_list.html'
template_name = 'assets/delete_confirm.html'
success_url = reverse_lazy('assets:asset-list')
class AssetDetailView(DetailView):
......@@ -56,6 +88,18 @@ class AssetDetailView(DetailView):
context_object_name = 'asset'
template_name = 'assets/asset_detail.html'
def get_context_data(self, **kwargs):
asset_groups = self.object.groups.all()
context = {
'app': 'Assets',
'action': 'Asset detail',
'asset_groups_remain': [asset_group for asset_group in AssetGroup.objects.all()
if asset_group not in asset_groups],
'asset_groups': asset_groups,
}
kwargs.update(context)
return super(AssetDetailView, self).get_context_data(**kwargs)
class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
model = AssetGroup
......
......@@ -100,3 +100,10 @@ def search_object_attr(obj, value='', attr_list=None, ignore_case=False):
def get_logger(name=None):
return logging.getLogger('jumpserver.%s' % name)
def int_seq(seq):
try:
return map(int, seq)
except ValueError:
return seq
This diff is collapsed.
{% extends '_list_base.html' %}
{% extends '_base_list.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
......
@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");
/** {*/
/*box-sizing: border-box;*/
/*}*/
/*.color {*/
/*color: #19BC9C !important;*/
/*}*/
/*html,*/
/*body {*/
/*width: 100%;*/
/*height: 100%;*/
/*margin: 0;*/
/*font-family: 'Ubuntu Condensed', sans-serif;*/
/*background-color: #fff;*/
/*}*/
/*h1 {*/
/*text-align: center;*/
/*margin-bottom: 32px;*/
/*}*/
div.container {
display: block;
width: 50%;
margin: 32px auto;
padding: 16px 32px;
background-color: #fff;
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.1);
}
div.inputTags-list {
display: inline-block;
width: 100%;
padding: 6px;
border: 1px solid rgba(25, 188, 156, 0.35);
/*background-color: #f9f9f9;*/
box-shadow: 1px 2px 2px rgba(221, 221, 221, 0.2);
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
-moz-background-clip: padding;
-webkit-background-clip: padding-box;
background-clip: padding-box;
}
div.inputTags-list span.inputTags-item {
position: relative;
display: inline-block;
margin: 2px;
padding: 3px 22px 4px 8px;
background-color: #19BC9C;
text-align: center;
color: #fff;
opacity: 1;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
-moz-background-clip: padding;
-webkit-background-clip: padding-box;
background-clip: padding-box;
}
div.inputTags-list span.inputTags-item.is-edit {
display: none;
}
div.inputTags-list span.inputTags-item.is-hidden {
display: none !important;
}
div.inputTags-list span.inputTags-item.is-exists {
background-color: rgba(231, 76, 60, 0.7);
}
div.inputTags-list span.inputTags-item span.value {
cursor: pointer;
}
div.inputTags-list span.inputTags-item i {
position: absolute;
top: 50%;
right: 6px;
font-size: 20px;
cursor: pointer;
z-index: 10;
font-weight: 400;
font-family: sans-serif;
line-height: 1;
font-style: normal;
-webkit-transition: color 0.2s;
-khtml-transition: color 0.2s;
-moz-transition: color 0.2s;
-ms-transition: color 0.2s;
-o-transition: color 0.2s;
-webkit-transform: translateY(-50%);
-khtml-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
}
div.inputTags-list span.inputTags-item i:hover {
color: #e74c3c;
}
div.inputTags-list input.inputTags-field {
border: none;
margin-left: 4px;
background-color: transparent;
}
div.inputTags-list input.inputTags-field:focus,
div.inputTags-list input.inputTags-field:active {
outline: none;
}
div.inputTags-list input.inputTags-field.is-edit {
margin: 0 2px;
padding: 4px 8px 3px 8px;
border: 1px dashed #c4c4c4;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
-moz-background-clip: padding;
-webkit-background-clip: padding-box;
background-clip: padding-box;
}
div.inputTags-list ul.inputTags-autocomplete-list {
position: absolute;
max-height: 192px;
margin: 0;
padding: 0;
list-style-type: none;
background-color: #fff;
border: 1px solid #ddd;
overflow-y: auto;
z-index: 100;
opacity: 0;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
-moz-background-clip: padding;
-webkit-background-clip: padding-box;
background-clip: padding-box;
-webkit-transform: scaleY(0);
-khtml-transform: scaleY(0);
-moz-transform: scaleY(0);
-ms-transform: scaleY(0);
-o-transform: scaleY(0);
-webkit-transform-origin: 50% 0;
-khtml-transform-origin: 50% 0;
-moz-transform-origin: 50% 0;
-ms-transform-origin: 50% 0;
-o-transform-origin: 50% 0;
-webkit-transition-duration: 0.2s;
-khtml-transition-duration: 0.2s;
-moz-transition-duration: 0.2s;
-ms-transition-duration: 0.2s;
-o-transition-duration: 0.2s;
}
div.inputTags-list ul.inputTags-autocomplete-list.is-active {
opacity: 1;
-webkit-transform: scaleY(1);
-khtml-transform: scaleY(1);
-moz-transform: scaleY(1);
-ms-transform: scaleY(1);
-o-transform: scaleY(1);
}
div.inputTags-list ul.inputTags-autocomplete-list li {
height: 32px;
line-height: 32px;
padding: 0 16px;
cursor: pointer;
border-bottom: 1px solid #ddd;
-webkit-transition-duration: 0.3s;
-khtml-transition-duration: 0.3s;
-moz-transition-duration: 0.3s;
-ms-transition-duration: 0.3s;
-o-transition-duration: 0.3s;
-webkit-transition-duration: 0.2s;
-khtml-transition-duration: 0.2s;
-moz-transition-duration: 0.2s;
-ms-transition-duration: 0.2s;
-o-transition-duration: 0.2s;
}
div.inputTags-list ul.inputTags-autocomplete-list li:last-child {
border: none;
}
div.inputTags-list ul.inputTags-autocomplete-list li:hover {
background-color: #19BC9C;
color: #fff;
}
div.inputTags-list ul.inputTags-autocomplete-list li.is-disabled {
cursor: default;
background-color: #f7f7f7;
color: initial;
}
p.inputTags-error {
position: relative;
margin: 0;
padding: 0.5em 1em;
color: #fff;
background-color: rgba(231, 76, 60, 0.7);
cursor: pointer;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
-moz-background-clip: padding;
-webkit-background-clip: padding-box;
background-clip: padding-box;
}
p.inputTags-error:first-of-type {
margin-top: 8px;
}
p.inputTags-error:after {
position: absolute;
content: "\000D7";
top: 50%;
right: 0.5em;
-webkit-transform: translateY(-50%);
-khtml-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
font-size: 28px;
}
This diff is collapsed.
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{% load bootstrap %}
{% block custom_head_css_js %}
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
{% block custom_head_css_js_create %} {% endblock %}
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>{{ action }}</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
{% block form %} {% endblock %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% extends 'users/_user.html' %}
{% load i18n %}
{% load bootstrap %}
{% block user_template_title %}{% trans "Create user" %}{% endblock %}
{% block username %}
{{ form.username|bootstrap_horizontal }}
{% endblock %}
......
<<<<<<< HEAD
{% extends '_list_base.html' %}
{% load i18n static %}
{% block custom_head_css_js %}
......@@ -5,6 +6,11 @@
<script src="{% static "js/plugins/sweetalert/sweetalert.min.js" %}"></script>
{% endblock %}
=======
{% extends '_base_list.html' %}
{% load i18n %}
{% load common_tags %}
>>>>>>> asset
{% block content_left_head %}
<a href="{% url 'users:user-group-create' %}" class="btn btn-sm btn-primary ">{% trans "Add User Group" %}</a>
{% endblock %}
......
{% extends '_list_base.html' %}
{% extends '_base_list.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
......
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