Commit 2aa9aafd authored by ibuler's avatar ibuler

[Change] Bulk update asset

parent 071d1922
......@@ -34,7 +34,7 @@ class AssetCreateForm(forms.ModelForm):
return self.cleaned_data['admin_user']
class AssetUpdateForm(AssetCreateForm):
class AssetUpdateForm(forms.ModelForm):
class Meta:
model = Asset
fields = [
......@@ -55,6 +55,23 @@ class AssetUpdateForm(AssetCreateForm):
}
class AssetBulkUpdateForm(forms.ModelForm):
class Meta:
model = Asset
fields = [
'port', 'groups', 'admin_user', 'idc',
'type', 'env', 'status',
]
widgets = {
'groups': forms.SelectMultiple(
attrs={'class': 'select2',
'data-placeholder': _('Select asset groups')}),
'admin_user': forms.Select(
attrs={'class': 'select2',
'data-placeholder': _('Select asset admin user')}),
}
class AssetGroupForm(forms.ModelForm):
# See AdminUserForm comment same it
assets = forms.ModelMultipleChoiceField(
......
{% extends '_modal.html' %}
{% load i18n %}
{% block modal_id %}asset_bulk_update_modal{% endblock %}
{% block modal_class %}modal-lg{% endblock %}
{% block modal_title%}{% trans "Update Asset" %}{% endblock %}
{% block modal_body %}
{% load bootstrap3 %}
<p class="text-success text-center">{% trans "Hint: only change the field you want to update." %}</p>
<div class="ydxbd" id="ydxbd" style="display: block;">
<div>
<p id="tags_p">
<a href="/assets/asset-by-tag/5">
<span class="label label-default">三年质保(0)</span>
</a>
</p>
</div>
</div>
<form method="post" class="form-horizontal" action="" id="fm_asset_bulk_update">
<div class="form-group">
<label class="control-label col-sm-2 col-lg-2 " for="id_type">{% trans "Asset type" %}</label>
<div class=" col-sm-9 col-lg-9 ">
<select class=" select2 form-control" id="id_type" name="type">
<option value="">---------</option>
<option value="Server">{% trans "Server" %}</option>
<option value="VM">{% trans "VM" %}</option>
<option value="Switch">{% trans "Switch" %}</option>
<option value="Storage">{% trans "Storage" %}</option>
<option value="Router">{% trans "Router" %}</option>
<option value="Firewall">{% trans "Firewall" %}</option>
</select>
</div>
</div>
<div class="form-group">
<label for="groups" class="col-sm-2 control-label">{% trans 'Asset Groups' %}</label>
<div class="col-sm-9" id="select2-container">
<select name="groups" id="select2_groups" data-placeholder="{% trans 'Select groups' %}" class="select2 form-control m-b" multiple>
{% for group in groups %}
<option value="{{ group.id }}">{{ group.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label for="users" class="col-sm-2 control-label">{% trans 'System users' %}</label>
<div class="col-sm-9" id="select2-container">
<select name="system_users" id="select2_users" data-placeholder="{% trans 'Select system users' %}" class="select2 form-control m-b" multiple>
{% for system_user in system_users %}
<option value="{{ system_user.id }}">{{ system_user.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-9 col-lg-9 col-sm-offset-2">
<div class="checkbox checkbox-success">
<input type="checkbox" name="enable_otp" checked id="id_enable_otp"><label for="id_enable_otp">{% trans 'Enable-OTP' %}</label>
</div>
</div>
</div>
</form>
{% endblock %}
{% block modal_confirm_id %}btn_asset_bulk_update{% endblock %}
\ No newline at end of file
{% extends '_base_create_update.html' %}
{% load static %}
{% load bootstrap3 %}
{% load i18n %}
{% block form %}
<div class="ydxbd" id="formlists" style="display: block;">
<p id="tags_p" class="mgl-5 c02">选择需要修改属性</p>
<div class="tagBtnList">
<a class="label label-primary" id="change_all" value="1">全选</a>
{% for field in form %}
<a data-id="{{ field.id_for_label }}" class="label label-default label-primary field-tag" value="1">{{ field.label }}</a>
{% endfor %}
</div>
</div>
{% if errors %}
<div class="alert alert-danger">
{{ errors }}
</div>
{% endif %}
<form method="post" class="form-horizontal" id="add_form">
{% csrf_token %}
<div class="form-group abc">
<label class="control-label col-sm-2 col-lg-2 " id="asset_on_count">{% trans 'Asset' %}</label>
<div class="col-sm-9">
<select class="form-control select2" multiple="multiple" name="assets">
{% for asset in assets %}
{% if asset.id in assets_selected %}
<option selected="selected" value="{{ asset.id }}">{{ asset.hostname }}</option>
{% else %}
<option value="{{ asset.id }}">{{ asset.hostname }}</option>
{% endif %}
{% endfor %}
</select>
<span class="help-block">* required</span>
</div>
</div>
{% bootstrap_form form layout="horizontal" %}
<div class="form-group abc">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
<button class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</form>
{% endblock %}
{% block custom_foot_js %}
<script>
$(document).ready(function () {
$('.select2').select2();
}).on('click', '.field-tag', function() {
changeField(this);
}).on('click', '#change_all', function () {
var tag_fields = $('.field-tag');
var $this = $(this);
var active = '1';
if ($this.attr('value') == '0'){
active = '0';
$this.attr('value', '1').addClass('label-primary')
} else {
active = '1';
$this.attr('value', '0').removeClass('label-primary')
}
$.each(tag_fields, function (k, v) {
changeField(v, active)
})
});
function changeField(obj, active) {
var $this = $(obj);
var field_id = $this.data('id');
if (!active) {
active = $this.attr('value');
}
if (active == '0') {
$this.attr('value', '1').addClass('label-primary');
var form_groups = $('#add_form .form-group:not(.abc)');
form_groups.filter(':has(#' + field_id + ')').show().find('select,input').prop('disabled', false)
} else {
$this.attr('value', '0').removeClass('label-primary');
var form_groups = $('#add_form .form-group:not(.abc)');
form_groups.filter(':has(#' + field_id + ')').hide().find('select,input').prop('disabled', true)
}
}
function fsubmit(){
var assets_id = document.getElementsByName("assets");
var oForm = document.getElementById('add_form');
var parentElem = document.getElementById("add_form");
var aDiv = parentElem.getElementsByClassName('form-group');
if (assets_id.length === 0) {
swal({
title: "未选择需要修改的主机",
text: "请点击选择"
});
}else if (aDiv.length === 1) {
swal({
title: "未选需要修改的属性",
text: "请点击选择"
});
}else{
var m = document.getElementsByName('assets_ids');
alert(m.length);
for(var i=0;i<m.length;i++){
alert(m[0].value);
oForm.appendChild(m[0]);
}
action="/assets/asset/"+assets_id[0].value+"/update";
oForm.action=action;
oForm.submit();
}
}
</script>
{% endblock %}
......@@ -5,12 +5,12 @@
<link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
<style>
.custom{
margin-right:5px;
}
#modal .modal-body { max-height: 200px; }
</style>
{#<style>#}
{# .custom{#}
{# margin-right:5px;#}
{# }#}
{# #modal .modal-body { max-height: 200px; }#}
{#</style>#}
{% endblock %}
{% block content_left_head %}{% endblock %}
......@@ -64,7 +64,7 @@
</div>
</div>
{% include 'assets/_asset_import_modal.html' %}
{% include 'assets/_asset_bulk_update_modal.html' %}
{#{% include 'assets/_asset_bulk_update_modal.html' %}#}
{% endblock %}
{% block custom_foot_js %}
......
{% extends '_base_create_update.html' %}
{% load static %}
{% load bootstrap3 %}
{% load i18n %}
{% block form %}
<div style="display:none" id="ridd">
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.type layout="horizontal" %}
{% bootstrap_field form.idc layout="horizontal" %}
{% bootstrap_field form.groups layout="horizontal" %}
{% bootstrap_field form.admin_user layout="horizontal" %}
{% bootstrap_field form.system_users layout="horizontal" %}
{% bootstrap_field form.brand layout="horizontal" %}
{% bootstrap_field form.cpu layout="horizontal" %}
{% bootstrap_field form.memory layout="horizontal" %}
{% bootstrap_field form.disk layout="horizontal" %}
{% bootstrap_field form.os layout="horizontal" %}
{% bootstrap_field form.cabinet_no layout="horizontal" %}
{% bootstrap_field form.cabinet_pos layout="horizontal" %}
{% bootstrap_field form.status layout="horizontal" %}
{% bootstrap_field form.env layout="horizontal" %}
{% bootstrap_field form.tags layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %}
</div>
<div class="hr-line-dashed"></div>
<form action="" class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2 col-lg-2 " id="asset_on_count">已选主机({{ assets_count }})</label>
<div class="col-sm-9" id="asset_sed">
<div class="form-asset-on" id="add_asset">
{% for asset in assets_on_list %}
<input type='hidden' name='assets' value='{{ asset.id }}'>
{% endfor %}
<p id="asset_on_p">
{% for asset in assets_on_list %}
<button name='asset_hostname' title='{{ asset.ip }}' type='button' class='btn btn-default btn-xs'>{{ asset.hostname }}</button>
{% endfor %}
</p>
</div>
</div>
</div>
</form>
<div class="hr-line-dashed"></div>
<div class="ydxbd" id="formlists" style="display: block;">
<p id="tags_p" class="mgl-5 c02">选择需要修改属性</p>
<div class="tagBtnList">
<a onclick="AddAllForm(this)" class="tagBtn2 label label-primary" id="changeall">全选</a>
<a onclick="AddForm(this,'id_port')" class="tagBtn2 label label-default" name="changebtn">端口</a>
<a onclick="AddForm(this,'id_type')" class="tagBtn2 label label-default" name="changebtn">系统类型</a>
<a onclick="AddForm(this,'id_idc')" class="tagBtn2 label label-default" name="changebtn">机房</a>
<a onclick="AddForm(this,'id_groups')" class="tagBtn2 label label-default" name="changebtn">用户组</a>
<a onclick="AddForm(this,'id_admin_user')" class="tagBtn2 label label-default" name="changebtn">管理用户</a>
<a onclick="AddForm(this,'id_system_users')" class="tagBtn2 label label-default" name="changebtn">系统用户</a>
<a onclick="AddForm(this,'id_brand')" class="tagBtn2 label label-default" name="changebtn">品牌</a>
<a onclick="AddForm(this,'id_cpu')" class="tagBtn2 label label-default" name="changebtn">CPU</a>
<a onclick="AddForm(this,'id_memory')" class="tagBtn2 label label-default" name="changebtn">内存</a>
<a onclick="AddForm(this,'id_disk')" class="tagBtn2 label label-default" name="changebtn">硬盘</a>
<a onclick="AddForm(this,'id_os')" class="tagBtn2 label label-default" name="changebtn">操作系统</a>
<a onclick="AddForm(this,'id_cabinet_no')" class="tagBtn2 label label-default" name="changebtn">机柜编号</a>
<a onclick="AddForm(this,'id_cabinet_pos')" class="tagBtn2 label label-default" name="changebtn">机柜层号</a>
<a onclick="AddForm(this,'id_status')" class="tagBtn2 label label-default" name="changebtn">资产状态</a>
<a onclick="AddForm(this,'id_env')" class="tagBtn2 label label-default" name="changebtn">资产环境</a>
<a onclick="AddForm(this,'id_tags')" class="tagBtn2 label label-default" name="changebtn">标签</a>
<a onclick="AddForm(this,'id_comment')" class="tagBtn2 label label-default" name="changebtn">备注</a>
</div>
</div>
<input name="assets_ids" type="hidden" value="111" >
<input name="assets_ids" type="hidden" value="112" >
<div class="hr-line-dashed"></div>
<form action="/assets/asset/27/update" method="post" class="form-horizontal" id="add_form">
{% csrf_token %}
<input name="ip" required="" type="hidden" value="1.0.0.0" >
<div class="form-group" name="formbtn" id="formbtn">
<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="button" onclick="fsubmit()">{% trans 'Submit' %}</button>
</div>
</div>
</form>
<!-- 模态框(Modal) -->
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content" id="box">
<!--此部分为主体内容,将远程加载进来-->
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
$('#add_asset').on('click',function(){
$('#modal').modal('show');
});
$('#modal').modal({
show: false,
backdrop: 'static',
keyboard: 'false',
remote:"{% url 'assets:asset-modal-list' %}?plain_id_lists={{ plain_id_lists }}",
});
$('#modal').on('show.bs.modal',function(){
//alert('当调用show方法时,立即触发;')
});
$('#modal').on('shown.bs.modal',function(){
//alert('当弹窗完全加载完后,再触发;')
});
$('#modal').on('hide.bs.modal',function(){
//alert('当关闭时,立即触发;')
});
$('#modal').on('hidden.bs.modal',function(){
//alert('当关完全关闭后,再触发;')
});
$('#modal').on('loaded.bs.modal',function(){
//alert('当远程数据加载完毕后,再触发;')
});
function SetSelect2(){
$('.select2').select2();
$("#id_tags").select2({
tags: true,
maximumSelectionLength: 8 //最多能够选择的个数
//closeOnSelect: false
});
}
function AddForm(obj,id_form) {
var oHiddenForms = document.getElementById("ridd");
var parentElem = document.getElementById("add_form");
var oH = document.getElementById(id_form);
var oNew = oH.parentNode.parentNode;
var aDiv = parentElem.getElementsByClassName('form-group');
if(oNew.parentNode.id=='ridd') {
obj.className="tagBtn2 label label-warning";
parentElem.insertBefore(oNew,aDiv[0]);
SetSelect2();
}else{
oHiddenForms.appendChild(oNew);
obj.className="tagBtn2 label label-default";
SetSelect2();
}
}
function ChangeBtnCss(class_var){
var changebtns = $("#formlists").find("a[name='changebtn']");
for (var i=0; i<changebtns.length;i++){
changebtns[i].className=class_var;
}
}
function AddAllForm(obj) {
var oHiddenForms = document.getElementById("ridd");
var parentElem = document.getElementById("add_form");
var aDiv = parentElem.getElementsByClassName('form-group');
var bFormBtn = document.getElementById("formbtn");
var oHidden_len = oHiddenForms.children.length;
var aDiv_len = aDiv.length;
if(oHidden_len == 0 || obj.innerText == "取消全选"){
for(var i=0;i<aDiv_len-1;i++){
oHiddenForms.appendChild(aDiv[0]);
}
ChangeBtnCss("tagBtn2 label label-default");
$('#changeall').text("全选");
}else{
for(var i=0;i<oHidden_len;i++){
parentElem.insertBefore(oHiddenForms.children[0],bFormBtn);
}
ChangeBtnCss("tagBtn2 label label-warning");
$('#changeall').text("取消全选");
SetSelect2();
}
}
function fsubmit(){
var assets_id = document.getElementsByName("assets");
var oForm = document.getElementById('add_form');
var parentElem = document.getElementById("add_form");
var aDiv = parentElem.getElementsByClassName('form-group');
if (assets_id.length === 0) {
swal({
title: "未选择需要修改的主机",
text: "请点击选择"
});
}else if (aDiv.length === 1) {
swal({
title: "未选需要修改的属性",
text: "请点击选择"
});
}else{
var m = document.getElementsByName('assets_ids');
alert(m.length);
for(var i=0;i<m.length;i++){
alert(m[0].value);
oForm.appendChild(m[0]);
}
action="/assets/asset/"+assets_id[0].value+"/update";
oForm.action=action;
oForm.submit();
}
}
</script>
{% endblock %}
......@@ -15,7 +15,7 @@ urlpatterns = [
url(r'^asset/(?P<pk>[0-9]+)/update/$', views.AssetUpdateView.as_view(), name='asset-update'),
url(r'^asset/(?P<pk>[0-9]+)/delete/$', views.AssetDeleteView.as_view(), name='asset-delete'),
url(r'^asset-modal$', views.AssetModalListView.as_view(), name='asset-modal-list'),
url(r'^asset-modal-update$', views.AssetModalCreateView.as_view(), name='asset-modal-update'),
url(r'^asset/update/$', views.AssetBulkUpdateView.as_view(), name='asset-bulk-update'),
# User asset view
url(r'^user-asset/$', views.UserAssetListView.as_view(), name='user-asset-list'),
......
......@@ -6,6 +6,7 @@ import json
import uuid
import codecs
from io import StringIO
from collections import defaultdict
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
......@@ -30,7 +31,7 @@ from ..tasks import update_assets_hardware_info
__all__ = ['AssetListView', 'AssetCreateView', 'AssetUpdateView',
'UserAssetListView', 'AssetModalCreateView', 'AssetDetailView',
'UserAssetListView', 'AssetBulkUpdateView', 'AssetDetailView',
'AssetModalListView', 'AssetDeleteView', 'AssetExportView',
'BulkImportAssetView',
]
......@@ -45,6 +46,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
'action': 'asset list',
'groups': AssetGroup.objects.all(),
'system_users': SystemUser.objects.all(),
# 'form': forms.AssetBulkUpdateForm(),
}
kwargs.update(context)
return super(AssetListView, self).get_context_data(**kwargs)
......@@ -89,32 +91,102 @@ class AssetCreateView(AdminUserRequiredMixin, CreateView):
return super(AssetCreateView, self).get_success_url()
class AssetModalCreateView(AdminUserRequiredMixin, ListView):
class AssetModalListView(AdminUserRequiredMixin, ListView):
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
model = Asset
form_class = forms.AssetCreateForm
template_name = 'assets/asset_modal_update.html'
context_object_name = 'asset_modal_list'
template_name = 'assets/asset_modal_list.html'
def get_context_data(self, **kwargs):
assets = Asset.objects.all()
assets_id = self.request.GET.get('assets_id', '')
assets_id_list = [i for i in assets_id.split(',') if i.isdigit()]
context = {
'all_assets': assets_id_list,
'assets': assets
}
kwargs.update(context)
return super(AssetModalListView, self).get_context_data(**kwargs)
class AssetBulkUpdateView(AdminUserRequiredMixin, ListView):
model = Asset
form_class = forms.AssetBulkUpdateForm
template_name = 'assets/asset_bulk_update.html'
success_url = reverse_lazy('assets:asset-list')
def get_queryset(self):
self.queryset = super(AssetModalCreateView,self).get_queryset()
self.s = self.request.GET.get('plain_id_lists')
if "," in str(self.s):
self.plain_id_lists = [int(x) for x in self.s.split(',')]
def get(self, request, *args, **kwargs):
assets_id = self.request.GET.get('assets_id', '')
self.assets_id_list = [int(i) for i in assets_id.split(',') if i.isdigit()]
self.form = self.form_class()
self.errors = kwargs.get('errors')
return super(AssetBulkUpdateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
raw_data = request.POST
data = {}
errors = defaultdict(list)
for k in raw_data:
if not hasattr(Asset, k) or raw_data.get(k) == '':
if k not in ['assets']:
continue
if k == 'assets':
v = Asset.objects.filter(id__in=raw_data.getlist(k))
if not v:
errors['assets'].append(_('Required'))
elif k == 'port':
try:
v = int(raw_data.get(k))
except ValueError:
v = None
errors['port'].append(_('Integer required'))
elif k == 'admin_user':
admin_user_id = raw_data.get(k)
try:
v = int(admin_user_id)
except ValueError:
v = None
errors['admin_user'].append(_('Invalid admin user'))
v = get_object_or_none(AdminUser, id=v)
elif k == 'groups':
groups_id = raw_data.getlist(k)
v = [AssetGroup.objects.filter(id__in=groups_id)]
elif k == 'idc':
idc_id = raw_data.get(k)
try:
v = int(idc_id)
except ValueError:
v = None
errors['idc'].append(_('Integer required'))
v = get_object_or_none(IDC, id=v)
else:
self.plain_id_lists = [self.s]
return self.queryset
v = raw_data.get(k)
data[k] = v
if not errors:
for asset in data['assets']:
for k, v in data.items():
if k == 'groups':
asset.groups.set(data['groups'])
else:
setattr(asset, k, v)
asset.save()
return redirect(reverse_lazy('assets:asset-list'))
else:
return self.get(request, errors=errors, *args, **kwargs)
def get_context_data(self, **kwargs):
asset_on_list = Asset.objects.filter(id__in = self.plain_id_lists)
# assets_list = Asset.objects.filter(id__in=self.assets_id_list)
context = {
'app': 'Assets',
'action': 'Bulk Update asset',
'assets_on_list': asset_on_list,
'assets_count': len(asset_on_list),
'plain_id_lists':self.s,
'action': 'Bulk update asset',
'form': self.form,
'errors': self.errors,
'assets_selected': self.assets_id_list,
'assets': Asset.objects.all(),
}
kwargs.update(context)
return super(AssetModalCreateView, self).get_context_data(**kwargs)
return super(AssetBulkUpdateView, self).get_context_data(**kwargs)
class AssetUpdateView(AdminUserRequiredMixin, UpdateView):
......@@ -164,44 +236,7 @@ class AssetDetailView(DetailView):
return super(AssetDetailView, self).get_context_data(**kwargs)
class AssetModalListView(AdminUserRequiredMixin, ListView):
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
model = Asset
context_object_name = 'asset_modal_list'
template_name = 'assets/asset_modal_list.html'
def get_context_data(self, **kwargs):
group_id = self.request.GET.get('group_id')
plain_id_lists = self.request.GET.get('plain_id_lists')
self.s = self.request.GET.get('plain_id_lists')
assets = Asset.objects.all()
if "," in str(self.s):
self.plain_id_lists = [int(x) for x in self.s.split(',')]
else:
self.plain_id_lists = [self.s]
if plain_id_lists:
if "," in str(self.s):
plain_id_lists = [int(x) for x in self.s.split(',')]
else:
plain_id_lists = [int(self.s)]
context = {
'all_assets': plain_id_lists,
}
kwargs.update(context)
if group_id:
group = AssetGroup.objects.get(id=group_id)
context = {
'all_assets': [x.id for x in group.assets.all()],
'assets': assets
}
kwargs.update(context)
else:
context = {
'assets': assets
}
kwargs.update(context)
return super(AssetModalListView, self).get_context_data(**kwargs)
@method_decorator(csrf_exempt, name='dispatch')
......
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