mirror of https://github.com/jumpserver/jumpserver
				
				
				
			资产相关API及Web
							parent
							
								
									4c06257070
								
							
						
					
					
						commit
						dbdb8a58fe
					
				|  | @ -3,67 +3,107 @@ | |||
| from rest_framework import viewsets, generics, mixins | ||||
| from rest_framework.response import Response | ||||
| from rest_framework.views import APIView | ||||
| from rest_framework_bulk import BulkModelViewSet, BulkDestroyAPIView | ||||
| from django_filters.rest_framework import DjangoFilterBackend | ||||
| from rest_framework_bulk import BulkListSerializer, BulkSerializerMixin, ListBulkCreateUpdateDestroyAPIView | ||||
| from django.shortcuts import get_object_or_404 | ||||
| 
 | ||||
| from common.mixins import IDInFilterMixin | ||||
| from common.utils import get_object_or_none, signer | ||||
| from .hands import IsSuperUserOrTerminalUser, IsSuperUser | ||||
| from .models import AssetGroup, Asset, IDC, SystemUser, AdminUser | ||||
| from .models import AssetGroup, Asset, IDC, SystemUser, AdminUser, Tag | ||||
| from . import serializers | ||||
| 
 | ||||
| 
 | ||||
| class AssetViewSet(IDInFilterMixin, viewsets.ModelViewSet): | ||||
| class AssetViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	"""API endpoint that allows Asset to be viewed or edited.""" | ||||
| 	queryset = Asset.objects.all() | ||||
| 	serializer_class = serializers.AssetSerializer | ||||
| 	filter_backends = (DjangoFilterBackend,) | ||||
| 	filter_fields = ('id', 'ip', 'hostname') | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| 	def get_queryset(self): | ||||
| 		queryset = super(AssetViewSet, self).get_queryset() | ||||
| 		idc_id = self.request.query_params.get('idc_id', '') | ||||
| 		tags_id = self.request.query_params.get('tag_id', '') | ||||
| 		system_users_id = self.request.query_params.get('system_user_id', '') | ||||
| 		asset_group_id = self.request.query_params.get('asset_group_id', '') | ||||
| 		admin_user_id = self.request.query_params.get('admin_user_id', '') | ||||
| 		if idc_id: | ||||
| 			queryset = queryset.filter(idc__id=idc_id) | ||||
| 
 | ||||
| 		if tags_id: | ||||
| 			queryset = queryset.filter(tags__id=tags_id) | ||||
| 		if system_users_id: | ||||
| 			queryset = queryset.filter(system_users__id=system_users_id) | ||||
| 		if admin_user_id: | ||||
| 			queryset = queryset.filter(admin_user__id=admin_user_id) | ||||
| 		if asset_group_id: | ||||
| 			queryset = queryset.filter(groups__id=asset_group_id) | ||||
| 		return queryset | ||||
| 
 | ||||
| 
 | ||||
| class AssetGroupViewSet(viewsets.ModelViewSet): | ||||
|     """ API endpoint that allows AssetGroup to be viewed or edited. | ||||
|         some other comment | ||||
|     """ | ||||
| class AssetGroupViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	queryset = AssetGroup.objects.all() | ||||
| 	serializer_class = serializers.AssetGroupSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class AssetUpdateGroupApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = Asset.objects.all() | ||||
| 	serializer_class = serializers.AssetUpdateGroupSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class IDCViewSet(viewsets.ModelViewSet): | ||||
| ## update the asset group, and add or delete the asset to the group | ||||
| class AssetGroupUpdateApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = AssetGroup.objects.all() | ||||
| 	serializer_class = serializers.AssetGroupUpdateSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| ## update the asset group, and add or delete the system_user to the group | ||||
| class AssetGroupUpdateSystemUserApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = AssetGroup.objects.all() | ||||
| 	serializer_class = serializers.AssetGroupUpdateSystemUserSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| ## update the IDC, and add or delete the assets to the IDC | ||||
| class IDCupdateAssetsApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = IDC.objects.all() | ||||
| 	serializer_class = serializers.IDCUpdateAssetsSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class IDCViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	"""API endpoint that allows IDC to be viewed or edited.""" | ||||
| 	queryset = IDC.objects.all() | ||||
| 	serializer_class = serializers.IDCSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class AdminUserViewSet(viewsets.ModelViewSet): | ||||
| class AdminUserViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	queryset = AdminUser.objects.all() | ||||
| 	serializer_class = serializers.AdminUserSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class SystemUserViewSet(viewsets.ModelViewSet): | ||||
| 
 | ||||
| class SystemUserViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	queryset = SystemUser.objects.all() | ||||
| 	serializer_class = serializers.SystemUserSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| 
 | ||||
| class SystemUserUpdateApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = Asset.objects.all() | ||||
| 	serializer_class = serializers.AssetUpdateSystemUserSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class SystemUserUpdateAssetsApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = SystemUser.objects.all() | ||||
| 	serializer_class = serializers.SystemUserUpdateAssetsSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class SystemUserUpdateAssetGroupApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = SystemUser.objects.all() | ||||
| 	serializer_class = serializers.SystemUserUpdateAssetGroupSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| 
 | ||||
| # class IDCAssetsApi(generics.ListAPIView): | ||||
| #     model = IDC | ||||
|  | @ -115,3 +155,14 @@ class SystemUserAuthApi(APIView): | |||
| 			return Response({'msg': 'error system user id or username'}, status=401) | ||||
| 
 | ||||
| 
 | ||||
| class TagViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	queryset = Tag.objects.all() | ||||
| 	serializer_class = serializers.TagSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| ## update the IDC, and add or delete the assets to the IDC | ||||
| class TagUpdateAssetsApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = Tag.objects.all() | ||||
| 	serializer_class = serializers.TagUpdateAssetsSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
|  |  | |||
|  | @ -37,6 +37,14 @@ class AssetCreateForm(forms.ModelForm): | |||
| 		self.instance.tags.clear() | ||||
| 		self.instance.tags.add(*tuple(tags)) | ||||
| 
 | ||||
| 	def clean(self): | ||||
| 		clean_data = super(AssetCreateForm, self).clean() | ||||
| 		ip = clean_data.get('ip') | ||||
| 		port = clean_data.get('port') | ||||
| 		query = Asset.objects.filter(ip=ip, port=port) | ||||
| 		if query: | ||||
| 			raise forms.ValidationError('this asset has exists.') | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = Asset | ||||
| 		tags = forms.ModelMultipleChoiceField(queryset=Tag.objects.all()) | ||||
|  | @ -293,10 +301,10 @@ class AssetTagForm(forms.ModelForm): | |||
| 		super(AssetTagForm, self).__init__(*args, **kwargs) | ||||
| 
 | ||||
| 	def _save_m2m(self): | ||||
|         super(AssetTagForm, self)._save_m2m() | ||||
| 		assets = self.cleaned_data['assets'] | ||||
|         self.instance.asset_set.clear() | ||||
|         self.instance.asset_set.add(*tuple(assets)) | ||||
| 		self.instance.assets.clear() | ||||
| 		self.instance.assets.add(*tuple(assets)) | ||||
| 		super(AssetTagForm, self)._save_m2m() | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = Tag | ||||
|  |  | |||
|  | @ -269,6 +269,19 @@ class AssetGroup(models.Model): | |||
| def get_default_idc(): | ||||
|     return IDC.initial() | ||||
| 
 | ||||
| class Tag(models.Model): | ||||
|     name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) | ||||
|     created_time = models.DateTimeField(auto_now_add=True, verbose_name=_('Create time')) | ||||
|     created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) | ||||
| 
 | ||||
|     def __unicode__(self): | ||||
|         return self.name | ||||
| 
 | ||||
|     __str__ = __unicode__ | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = 'tag' | ||||
| 
 | ||||
| 
 | ||||
| class Asset(models.Model): | ||||
|     STATUS_CHOICES = ( | ||||
|  | @ -320,7 +333,7 @@ class Asset(models.Model): | |||
|     is_active = models.BooleanField(default=True, verbose_name=_('Is active')) | ||||
|     date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date added')) | ||||
|     comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment')) | ||||
|     tags = models.ManyToManyField('Tag', blank=True, verbose_name=_('Tags')) | ||||
|     tags = models.ManyToManyField(Tag, related_name='assets', blank=True, verbose_name=_('Tags')) | ||||
| 
 | ||||
|     def __unicode__(self): | ||||
|         return '%(ip)s:%(port)s' % {'ip': self.ip, 'port': self.port} | ||||
|  | @ -339,7 +352,7 @@ class Asset(models.Model): | |||
| 
 | ||||
|     class Meta: | ||||
|         db_table = 'asset' | ||||
|         unique_together = ('ip', 'port') | ||||
|         # unique_together = ('ip', 'port') | ||||
| 
 | ||||
|     @classmethod | ||||
|     def generate_fake(cls, count=100): | ||||
|  | @ -365,18 +378,7 @@ class Asset(models.Model): | |||
|                 continue | ||||
| 
 | ||||
| 
 | ||||
| class Tag(models.Model): | ||||
|     name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) | ||||
|     created_time = models.DateTimeField(auto_now_add=True, verbose_name=_('Create time')) | ||||
|     created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) | ||||
| 
 | ||||
|     def __unicode__(self): | ||||
|         return self.name | ||||
| 
 | ||||
|     __str__ = __unicode__ | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = 'tag' | ||||
| 
 | ||||
| 
 | ||||
| def init_all_models(): | ||||
|  |  | |||
|  | @ -1,17 +1,18 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| from django.utils.translation import ugettext_lazy as _ | ||||
| from rest_framework import viewsets, serializers,generics | ||||
| from .models import AssetGroup, Asset, IDC, AdminUser, SystemUser | ||||
| from .models import AssetGroup, Asset, IDC, AdminUser, SystemUser, Tag | ||||
| from common.mixins import IDInFilterMixin | ||||
| from rest_framework_bulk import BulkListSerializer, BulkSerializerMixin | ||||
| 
 | ||||
| 
 | ||||
| class AssetGroupSerializer(serializers.ModelSerializer): | ||||
| class AssetGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer): | ||||
| 	assets_amount = serializers.SerializerMethodField() | ||||
|     # assets = serializers.PrimaryKeyRelatedField(many=True, read_only=True) | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = AssetGroup | ||||
| 		list_serializer_class = BulkListSerializer | ||||
| 
 | ||||
| 	@staticmethod | ||||
| 	def get_assets_amount(obj): | ||||
|  | @ -31,7 +32,43 @@ class AssetUpdateSystemUserSerializer(serializers.ModelSerializer): | |||
| 		model = Asset | ||||
| 		fields = ['id', 'system_users'] | ||||
| 
 | ||||
| ## update the asset group, and add or delete the asset to the group | ||||
| class AssetGroupUpdateSerializer(serializers.ModelSerializer): | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = AssetGroup | ||||
| 		fields = ['id', 'assets'] | ||||
| 
 | ||||
| ## update the asset group, and add or delete the system_user to the group | ||||
| class AssetGroupUpdateSystemUserSerializer(serializers.ModelSerializer): | ||||
| 	system_users = serializers.PrimaryKeyRelatedField(many=True, queryset=SystemUser.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = AssetGroup | ||||
| 		fields = ['id', 'system_users'] | ||||
| 
 | ||||
| ## update the IDC, and add or delete the assets to the IDC | ||||
| class IDCUpdateAssetsSerializer(serializers.ModelSerializer): | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = IDC | ||||
| 		fields = ['id', 'assets'] | ||||
| 
 | ||||
| ## tags API | ||||
| class TagSerializer(BulkSerializerMixin, serializers.ModelSerializer): | ||||
| 	assets_amount = serializers.SerializerMethodField() | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = Tag | ||||
| 		list_serializer_class = BulkListSerializer | ||||
| 
 | ||||
| 	@staticmethod | ||||
| 	def get_assets_amount(obj): | ||||
| 		return obj.assets.count() | ||||
| 
 | ||||
| 
 | ||||
| class AdminUserSerializer(serializers.ModelSerializer): | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = AdminUser | ||||
| 
 | ||||
|  | @ -52,6 +89,20 @@ class SystemUserSerializer(serializers.ModelSerializer): | |||
| 		return fields | ||||
| 
 | ||||
| 
 | ||||
| class SystemUserUpdateAssetsSerializer(serializers.ModelSerializer): | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = SystemUser | ||||
| 		fields = ['id', 'assets'] | ||||
| 
 | ||||
| 
 | ||||
| class SystemUserUpdateAssetGroupSerializer(serializers.ModelSerializer): | ||||
| 	asset_groups = serializers.PrimaryKeyRelatedField(many=True, queryset=AssetGroup.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = SystemUser | ||||
| 		fields = ['id', 'asset_groups'] | ||||
| 
 | ||||
| 
 | ||||
| class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): | ||||
| 	# system_users = SystemUserSerializer(many=True, read_only=True) | ||||
| 	# admin_user = AdminUserSerializer(many=False, read_only=True) | ||||
|  | @ -96,8 +147,9 @@ class AssetGrantedSerializer(serializers.ModelSerializer): | |||
| 		return ', '.join([system_user.username for system_user in obj.system_users.all()]) | ||||
| 
 | ||||
| 
 | ||||
| class IDCSerializer(serializers.ModelSerializer): | ||||
| class IDCSerializer(BulkSerializerMixin, serializers.ModelSerializer): | ||||
| 	assets_amount = serializers.SerializerMethodField() | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = IDC | ||||
|  | @ -110,3 +162,11 @@ class IDCSerializer(serializers.ModelSerializer): | |||
| 		fields = super(IDCSerializer, self).get_field_names(declared_fields, info) | ||||
| 		fields.append('assets_amount') | ||||
| 		return fields | ||||
| 
 | ||||
| 
 | ||||
| class TagUpdateAssetsSerializer(serializers.ModelSerializer): | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = Tag | ||||
| 		fields = ['id', 'assets'] | ||||
|  | @ -6,8 +6,7 @@ | |||
| {% block modal_body %} | ||||
| {% load bootstrap %} | ||||
| <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 class="ydxbd" id="ydxbd" style="display: block;"> | ||||
| 	<div> | ||||
| 		<p id="tags_p"> | ||||
| 			<a href="/assets/asset-by-tag/5"> | ||||
|  | @ -15,21 +14,25 @@ | |||
| 			</a> | ||||
| 		</p> | ||||
| 	</div> | ||||
|                        </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_role">{% trans "Role" %}</label> | ||||
|         <label class="control-label col-sm-2 col-lg-2 " for="id_type">{% trans "System Type" %}</label> | ||||
|         <div class=" col-sm-9 col-lg-9 "> | ||||
|             <select class=" select2 form-control" id="id_role" name="role"> | ||||
|             <select class=" select2 form-control" id="id_type" name="type"> | ||||
|                 <option value="">---------</option> | ||||
|                 <option value="Admin">{% trans "Admin" %}</option> | ||||
|                 <option value="User">{% trans "User" %}</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 'Groups' %}</label> | ||||
|     <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 Group' %}" class="select2 form-control m-b" multiple> | ||||
|                 {% for group in groups %} | ||||
|  | @ -38,6 +41,18 @@ | |||
|             </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"> | ||||
|  | @ -48,27 +63,16 @@ | |||
| 
 | ||||
| 
 | ||||
| <div class="form-group"> | ||||
| 
 | ||||
| 
 | ||||
| 	<label class="control-label col-sm-2 col-lg-2 " for="id_tags">标签集合</label> | ||||
| 
 | ||||
| 
 | ||||
| 	<div class=" col-sm-9 col-lg-9 "> | ||||
| 		<select multiple="multiple" class="select2 form-control" data-placeholder="Select asset tags" id="tags" name="tags"> | ||||
| <option value="1">物理机</option> | ||||
| <option value="2">虚拟机</option> | ||||
| <option value="3">数据库备份</option> | ||||
| <option value="4">亦庄机房</option> | ||||
| <option value="5">三年质保</option> | ||||
| </select> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 			{% for tag in tags %} | ||||
| 				<option value="{{ tag.id }}">{{ tag.name }}</option> | ||||
| 			{% endfor %} | ||||
| 		</select> | ||||
| 		<p class="help-block"> | ||||
| 			最多5个标签,单个标签最长8个汉字,按回车确认 | ||||
| 		</p> | ||||
| 
 | ||||
| 	</div> | ||||
| 
 | ||||
| </div> | ||||
|  |  | |||
|  | @ -0,0 +1,42 @@ | |||
| {% extends '_modal.html' %} | ||||
| {% load i18n %} | ||||
| {% block modal_id %}asset_group_bulk_update_modal{% endblock %} | ||||
| {% block modal_class %}modal-lg{% endblock %} | ||||
| {% block modal_title%}{% trans "Update Asset Group" %}{% endblock %} | ||||
| {% block modal_body %} | ||||
| {% load bootstrap %} | ||||
| <p class="text-success text-center">{% trans "Hint: only change the field you want to update." %}</p> | ||||
| <form method="post" class="form-horizontal" action="" id="fm_asset_group_bulk_update"> | ||||
| 
 | ||||
|     <div class="form-group"> | ||||
|         <label for="assets" class="col-sm-2 control-label">{% trans 'Assets' %}</label> | ||||
|         <div class="col-sm-9" id="select2-container"> | ||||
|             <select name="assets" id="select2_groups" data-placeholder="{% trans 'Select Asset' %}" class="select2 form-control m-b" multiple> | ||||
|                 {% for asset in assets %} | ||||
|                     <option value="{{ asset.id }}">{{ asset.ip }}</option> | ||||
|                 {% endfor %} | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
| 	<div class="form-group"> | ||||
|         <label for="system_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_groups" 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_group_bulk_update{% endblock %} | ||||
|  | @ -88,29 +88,30 @@ | |||
|                                     </div> | ||||
|                                 </div> | ||||
|                                 <div class="ibox-content"> | ||||
|                                     <table class="table table-hover"> | ||||
|                                     <table class="table table-hover" id="system_user_assets_table"> | ||||
|                                         <thead> | ||||
|                                             <tr> | ||||
|                                                 <th>{% trans 'Hostname' %}</th> | ||||
|                                                 <th>{% trans 'IP' %}</th> | ||||
|                                                 <th>{% trans 'Port' %}</th> | ||||
|                                                 <th>{% trans 'Alive' %}</th> | ||||
| 	                                            <th>{% trans 'Action' %}</th> | ||||
|                                             </tr> | ||||
|                                         </thead> | ||||
|                                         <tbody> | ||||
|                                             {% for asset in page_obj %} | ||||
|                                             <tr> | ||||
|                                                 <td>{{ asset.hostname }}</td> | ||||
|                                                 <td>{{ asset.ip }}</td> | ||||
|                                                 <td>{{ asset.port }}</td> | ||||
|                                                 <td>Alive</td> | ||||
|                                             </tr> | ||||
|                                             {% endfor %} | ||||
| {#                                            {% for asset in page_obj %}#} | ||||
| {#                                            <tr>#} | ||||
| {#                                                <td>{{ asset.hostname }}</td>#} | ||||
| {#                                                <td>{{ asset.ip }}</td>#} | ||||
| {#                                                <td>{{ asset.port }}</td>#} | ||||
| {#                                                <td>Alive</td>#} | ||||
| {#                                            </tr>#} | ||||
| {#                                            {% endfor %}#} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                     <div class="row"> | ||||
|                                         {% include '_pagination.html' %} | ||||
|                                     </div> | ||||
| {#                                    <div class="row">#} | ||||
| {#                                        {% include '_pagination.html' %}#} | ||||
| {#                                    </div>#} | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|  | @ -164,15 +165,15 @@ | |||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select asset' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for group in groups %} | ||||
|                                                             <option value="{{ group.id }}">{{ group.name }}</option> | ||||
|                                                         {% for asset in assets_remain %} | ||||
|                                                             <option value="{{ asset.id }}">{{ asset.ip }}:{{ asset.port }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm">{% trans 'Replace' %}</button> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm btn-replace-asset-admin_user">{% trans 'Replace' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|  | @ -192,15 +193,15 @@ | |||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select asset groups' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for group in groups %} | ||||
|                                                             <option value="{{ group.id }}">{{ group.name }}</option> | ||||
|                                                         {% for asset_group in asset_groups %} | ||||
|                                                             <option value="{{ asset_group.id }}">{{ asset_group.name }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-warning btn-sm">{% trans 'Replace' %}</button> | ||||
|                                                     <button type="button" class="btn btn-warning btn-sm btn-replace-asset_groups-admin_user">{% trans 'Replace' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|  | @ -218,26 +219,181 @@ | |||
| 
 | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
| {#        function switch_user_status(obj) {#} | ||||
| {#            var status = $(obj).prop('checked');#} | ||||
| {##} | ||||
| {#            $.ajax({#} | ||||
| {#                url: "{% url 'users:user-active-api' pk=user.id %}",#} | ||||
| {#                type: "PUT",#} | ||||
| {#                data: {#} | ||||
| {#                    'is_active': status#} | ||||
| {#                },#} | ||||
| {#                success: function (data, status) {#} | ||||
| {#                    console.log(data)#} | ||||
| {#                },#} | ||||
| {#                error: function () {#} | ||||
| {#                    console.log('error')#} | ||||
| {#                }#} | ||||
| {#            })#} | ||||
| {#        }#} | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
| <script> | ||||
| Array.prototype.remove = function(val) { | ||||
| 	var index = this.indexOf(val); | ||||
| 		if (index > -1) { | ||||
| 		this.splice(index, 1); | ||||
| 	} | ||||
| }; | ||||
| Array.prototype.unique = function(){ | ||||
| 	var res = []; | ||||
| 	var json = {}; | ||||
|  	for(var i = 0; i < this.length; i++){ | ||||
|   		if(!json[this[i]]){ | ||||
|    			res.push(this[i]); | ||||
|    			json[this[i]] = 1; | ||||
|   		} | ||||
|  	} | ||||
|  	return res; | ||||
| }; | ||||
| function objectRemove(obj, name, url, data) { | ||||
|     function doRemove() { | ||||
|         var body = data; | ||||
|         var success = function() { | ||||
|             swal('Remove!', "[ "+name+"]"+" has been deleted ", "success"); | ||||
|             $(obj).parent().parent().remove(); | ||||
|         }; | ||||
|         var fail = function() { | ||||
|             swal("Failed", "Remove"+"[ "+name+" ]"+"failed", "error"); | ||||
|         }; | ||||
|         APIUpdateAttr({ | ||||
|             url: url, | ||||
|             body: JSON.stringify(body), | ||||
|             method: 'PATCH', | ||||
|             success: success, | ||||
|             error: fail | ||||
|         }); | ||||
|     </script> | ||||
|     } | ||||
|     swal({ | ||||
|         title: 'Are you sure remove ?', | ||||
|         text: " [" + name + "] ", | ||||
|         type: "warning", | ||||
|         showCancelButton: true, | ||||
|         cancelButtonText: 'Cancel', | ||||
|         confirmButtonColor: "#DD6B55", | ||||
|         confirmButtonText: 'Confirm', | ||||
|         closeOnConfirm: false | ||||
|     }, function () { | ||||
|         doRemove() | ||||
|     }); | ||||
| } | ||||
| jumpserver.assets_selected = {}; | ||||
| jumpserver.asset_groups_selected = {}; | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2() | ||||
| 	.on("select2:select", function (evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		jumpserver.assets_selected[data.id] = data.text; | ||||
| 		jumpserver.asset_groups_selected[data.id] = data.text; | ||||
| 	}) | ||||
| 	.on('select2:unselect', function(evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		delete jumpserver.assets_selected[data.id]; | ||||
| 		delete jumpserver.asset_groups_selected[data.id] | ||||
| 	}); | ||||
| 	var options = { | ||||
| 		ele: $('#system_user_assets_table'), | ||||
| 		buttons: [], | ||||
| 		order: [], | ||||
| 		columnDefs: [ | ||||
| 			{targets: 0, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}" data-aid="'+rowData.id+'">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 3, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-times text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-check text-navy"></i>') | ||||
| 				} | ||||
| 			}}, | ||||
| 			{targets: 4, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', rowData.id); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_remove" data-aid="99991937">{% trans "Remove" %}</a>'.replace('99991937', rowData.id); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 
 | ||||
| 			], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}?admin_user_id={{ admin_user.id }}', | ||||
| 		columns: [{data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
| 			{data: "is_active" }, {data: "id"}], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-replace-asset-admin_user', function () { | ||||
| 	if (Object.keys(jumpserver.assets_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	jumpserver.asset_groups_selected = {}; | ||||
| 	var $data_table = $("#system_user_assets_table").DataTable(); | ||||
| 	var assets = []; | ||||
| 	$.map(jumpserver.assets_selected, function(value, index) { | ||||
| 		assets.push(parseInt(index)); | ||||
| 	}); | ||||
| 	assets.unique(); | ||||
| 	var data = []; | ||||
| 	var admin_user_id = {{ admin_user.id }}; | ||||
| 	var the_url = '{% url "api-assets:asset-list" %}'; | ||||
| 	for (var i=0; i<assets.length; i++) { | ||||
| 		data.push({"id": assets[i], "admin_user": admin_user_id}); | ||||
| 	} | ||||
| 	APIUpdateAttr({ | ||||
| 		url: the_url, | ||||
| 		body: JSON.stringify(data), | ||||
| 		method: 'PATCH' | ||||
| 	}); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-replace-asset_groups-admin_user', function () { | ||||
| 	if (Object.keys(jumpserver.asset_groups_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	jumpserver.assets_selected = {}; | ||||
| 	var $data_table = $("#system_user_assets_table").DataTable(); | ||||
| 	var asset_groups = []; | ||||
| 	var assets = []; | ||||
| 	var data = []; | ||||
| 	var the_url = '{% url "api-assets:asset-list" %}'; | ||||
| 	$.map(jumpserver.asset_groups_selected, function(value, index) { | ||||
| 		asset_groups.push(parseInt(index)); | ||||
| 	}); | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:asset-group-list" %}?id__in=['+asset_groups.join(',')+']', | ||||
| 		method: 'GET', | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for (var i=0; i<result.length; i++) { | ||||
| 				for (var j=0; j<result[i]['assets'].length; j++) { | ||||
| 					assets.push(result[i]['assets'][j]) | ||||
| 				} | ||||
| 			} | ||||
| 			for (var z=0; z<assets.length; z++) { | ||||
| 				data.push({"id":assets[z], "admin_user":{{admin_user.id}} }); | ||||
| 			} | ||||
| 			APIUpdateAttr({ | ||||
| 				url: the_url, | ||||
| 				body: JSON.stringify(data), | ||||
| 				method: 'PATCH' | ||||
| 			}); | ||||
| 			$data_table.ajax.reload(); | ||||
| 		} | ||||
| 	}); | ||||
| }) | ||||
| 	 | ||||
| .on('click', '.btn_asset_remove', function () { | ||||
| 	var $this = $(this); | ||||
| 	var the_url = "{% url 'api-assets:admin-user-detail' pk=admin_user.id %}"; | ||||
| 	var name = $(this).closest("tr").find(":nth-child(1) > a").html(); | ||||
| 	var assets = []; | ||||
| 	var delete_asset_id = $(this).data('aid'); | ||||
| 	$.ajax({ | ||||
| 		url: the_url, | ||||
| 		method: 'GET', | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for (var i=0; i<result['assets'].length; i++) { | ||||
| 				assets.push(result['assets'][i]) | ||||
| 			} | ||||
| 			assets.remove(delete_asset_id); | ||||
| 			var data = {"assets": assets}; | ||||
| 			objectRemove($this, name, the_url, data); | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -23,6 +23,18 @@ | |||
|     <tbody> | ||||
|     </tbody> | ||||
| </table> | ||||
| <div id="actions" class="hide"> | ||||
|     <div class="input-group"> | ||||
|         <select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
|             <option value="delete">{% trans 'Delete selected' %}</option> | ||||
|         </select> | ||||
|         <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
|             <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary"> | ||||
|              {% trans 'Submit' %} | ||||
|             </button> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| {% endblock %} | ||||
| {% block content_bottom_left %}{% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|  | @ -48,8 +60,72 @@ $(document).ready(function(){ | |||
|         ajax_url: '{% url "api-assets:admin-user-list" %}', | ||||
|         columns: [{data: function(){return ""}}, {data: "name" }, {data: "username" }, {data: "assets_amount" }, {data: function () {return 'lost'} }, | ||||
|                   {data: "comment" }, {data: "id" }], | ||||
| 	    op_html: $('#actions').html() | ||||
|     }; | ||||
|     jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_admin_user_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $("#admin_user_list_table").DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:admin-user-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $('#slct_bulk_update').val(); | ||||
| 	var $data_table = $('#admin_user_list_table').DataTable(); | ||||
| 	var id_list = []; | ||||
|     var plain_id_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (plain_id_list.length == 0) { | ||||
|         return false; | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:admin-user-list' %}"; | ||||
|     function doDelete() { | ||||
|         swal({ | ||||
|             title: "{% trans 'Are you sure?' %}", | ||||
|             text: "{% trans 'This will delete the selected Admin Users !!!' %}", | ||||
|             type: "warning", | ||||
|             showCancelButton: true, | ||||
|             confirmButtonColor: "#DD6B55", | ||||
|             confirmButtonText: "{% trans 'Confirm' %}", | ||||
|             closeOnConfirm: false | ||||
|         }, function() { | ||||
|             var success = function() { | ||||
|                 var msg = "{% trans 'Admin Users Deleted.' %}"; | ||||
|                 swal("{% trans 'Admin Users Delete' %}", msg, "success"); | ||||
|                 $('#admin_user_list_table').DataTable().ajax.reload(); | ||||
|             }; | ||||
|             var fail = function() { | ||||
|                 var msg = "{% trans 'Admin Users Deleting failed.' %}"; | ||||
|                 swal("{% trans 'Admin Users Delete' %}", msg, "error"); | ||||
|             }; | ||||
|             var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); | ||||
|             APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail}); | ||||
|             $data_table.ajax.reload(); | ||||
|             jumpserver.checked = false; | ||||
|         }); | ||||
|     } | ||||
|     function doUpdate() { | ||||
| 
 | ||||
|     } | ||||
|     switch (action) { | ||||
| 	    case 'delete': | ||||
| 	    	doDelete(); | ||||
| 	    	break; | ||||
| 	    case 'update': | ||||
| 	    	doUpdate(); | ||||
| 	    	break; | ||||
| 	    default: | ||||
| 	    	break; | ||||
|     } | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  |  | |||
|  | @ -200,7 +200,7 @@ | |||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Asset groups' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table group_edit"> | ||||
|                                     <table class="table group_edit" id="add-asset2group"> | ||||
|                                         <tbody> | ||||
|                                         <form> | ||||
|                                             <tr> | ||||
|  | @ -236,7 +236,7 @@ | |||
|                                     <i class="fa fa-info-circle"></i> {% trans 'System users' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table group_edit"> | ||||
|                                     <table class="table group_edit" id="add-asset2systemuser"> | ||||
|                                         <tbody> | ||||
|                                         <form> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|  | @ -288,7 +288,7 @@ function updateAssetGroups(groups) { | |||
|         $.map(jumpserver.groups_selected, function(group_name, index) { | ||||
|             $('#opt_' + index).remove(); | ||||
|             // change tr html of user groups. | ||||
|             $('.group_edit tbody').append( | ||||
|             $('#add-asset2group tbody').append( | ||||
|                 '<tr>' + | ||||
|                 '<td><b class="bdg_group" data-gid="' + index + '">' + group_name + '</b></td>' + | ||||
|                 '<td><button class="btn btn-danger btn-xs pull-right btn_leave_group" type="button"><i class="fa fa-minus"></i></button></td>' + | ||||
|  | @ -316,7 +316,7 @@ function updateAssetSystem(system_users) { | |||
|         $.map(jumpserver.groups_selected, function(name, index) { | ||||
|             $('#opt_' + index).remove(); | ||||
| 
 | ||||
|             $('.group_edit tbody').append( | ||||
|             $('#add-asset2systemuser tbody').append( | ||||
|                 '<tr>' + | ||||
|                 '<td><b class="bdg_group" data-sid="' + index + '">' + name + '</b></td>' + | ||||
|                 '<td><button class="btn btn-danger btn-xs pull-right btn_leave_system" type="button"><i class="fa fa-minus"></i></button></td>' + | ||||
|  | @ -418,7 +418,6 @@ $(document).ready(function () { | |||
| 	    var system_users = $('.bdg_group').map(function () { | ||||
| 	        return $(this).data('sid'); | ||||
| 	    }).get(); | ||||
| 	    console.log(system_users); | ||||
| 	    updateAssetSystem(system_users) | ||||
| 
 | ||||
| }) | ||||
|  |  | |||
|  | @ -48,10 +48,28 @@ | |||
|                                                 <th>{% trans 'Hostname' %}</th> | ||||
|                                                 <th>{% trans 'IP' %}</th> | ||||
|                                                 <th>{% trans 'Port' %}</th> | ||||
| 	                                            <th>{% trans 'Type' %}</th> | ||||
|                                                 <th>{% trans 'Alive' %}</th> | ||||
| 	                                            <th>{% trans 'Action' %}</th> | ||||
|                                             </tr> | ||||
|                                         </thead> | ||||
|                                         <tbody> | ||||
| {#                                        {% for asset in assets %}#} | ||||
| {#                                            <tr id="bdg_asset" data-aid="{{ asset.id }}">#} | ||||
| {#                                                <td>{{ asset.hostname }}</td>#} | ||||
| {#                                                <td>{{ asset.ip }}</td>#} | ||||
| {#                                                <td>{{ asset.port }}</td>#} | ||||
| {#                                                {% if asset.is_active %}#} | ||||
| {#	                                                <td><i class="fa fa-circle text-navy"></i></td>#} | ||||
| {#	                                            {% else %}#} | ||||
| {#	                                                <td><i class="fa fa-circle text-danger"></i></td>#} | ||||
| {#	                                            {% endif %}#} | ||||
| {#                                                <td>#} | ||||
| {#	                                                <a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-aid="{{ asset.id }}">{% trans "Delete" %}</a>#} | ||||
| {#	                                                <a class="btn btn-xs btn-info m-l-xs btn_asset_update" data-aid="{{ asset.id }}" href="{% url 'assets:asset-update' pk=asset.id %}">{% trans "Update" %}</a>#} | ||||
| {#                                                </td>#} | ||||
| {#                                            </tr>#} | ||||
| {#                                        {% endfor %}#} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                 </div> | ||||
|  | @ -70,14 +88,14 @@ | |||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select assets' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for asset in assets_remain %} | ||||
|                                                             <option value="{{ asset.id }}">{{ asset.ip }}:{{ asset.port }}</option> | ||||
|                                                             <option value="{{ asset.id }}" id="opt_{{ asset.id }}">{{ asset.ip }}:{{ asset.port }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm">{% trans 'Add' %}</button> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm btn-asset-add-groups">{% trans 'Add' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|  | @ -91,29 +109,29 @@ | |||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Associate system user' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table"> | ||||
|                                     <table class="table system-user-table"> | ||||
|                                         <tbody> | ||||
|                                         <form> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select system user' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for system_user in system_users_remain %} | ||||
|                                                             <option value="{{ system_user.id }}">{{ system_user.name }}</option> | ||||
|                                                             <option value="{{ system_user.id }}" id="opt_{{ system_user.id }}">{{ system_user.name }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm">{% trans 'Associate' %}</button> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm btn-asset-add-groups-system-users">{% trans 'Associate' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|                                         {% for system_user in system_users %} | ||||
|                                         <tr> | ||||
|                                             <td ><b>{{ group.name }}</b></td> | ||||
|                                             <td ><b class="bdg_system_user" data-sid={{ system_user.id }}>{{ system_user.name }}</b></td> | ||||
|                                             <td> | ||||
|                                                 <button class="btn btn-danger btn-xs" type="button" style="float: right;"><i class="fa fa-minus"></i></button> | ||||
|                                                 <button class="btn btn-danger btn-xs pull-right btn_leave_asset_group" type="button" style="float: right;"><i class="fa fa-minus"></i></button> | ||||
|                                             </td> | ||||
|                                         </tr> | ||||
|                                         {% endfor %} | ||||
|  | @ -132,53 +150,249 @@ | |||
| 
 | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
| <script> | ||||
| jumpserver.assets_selected = {}; | ||||
| jumpserver.system_users_selected = {}; | ||||
| function updateAssetsGroup(assets) { | ||||
|     var the_url = "{% url 'api-assets:asset-groups-update' pk=asset_group.id %}"; | ||||
|     var body = { | ||||
|         assets: Object.assign([], assets) | ||||
|     }; | ||||
|     var success = function(data) { | ||||
|         $('select2-selection__rendered').empty(); | ||||
|         $('#groups_selected').val(''); | ||||
|         $('#asset_list_table > tbody').empty(); | ||||
|         $.map(jumpserver.assets_selected, function(asset_ip, index) { | ||||
|         	var url = '{% url "api-assets:asset-detail" pk=99991937 %}'.replace(99991937, index); | ||||
|         	asset = $.ajax({ | ||||
|         		url: url, | ||||
| 		        method: "GET", | ||||
| 		        dataType: "json", | ||||
| 		        success: function (data, textStatus) { | ||||
| 			        var add_tr = '<tr id="bdg_asset" data-aid="'+data.id+'">'+ | ||||
| 				        '<td>'+data.hostname+'</td>'+ | ||||
| 				        '<td>'+data.ip+'</td>'+ | ||||
| 				        '<td>'+data.port+'</td>'+ | ||||
| 				        '<td>status</td>'+ | ||||
| 				        '<td>'+ | ||||
| 				        '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-aid="'+data.id+'">{% trans "Delete" %}</a>'+ | ||||
| 					    '<a class="btn btn-xs btn-info m-l-xs btn_asset_update" data-aid="'+data.id+'" href="'+'{% url "assets:asset-update" pk=99991937 %}'.replace(99991937, data.id)+'">{% trans "Update" %}</a>'+ | ||||
| 				        '</td>'+ | ||||
| 			            '</tr>'; | ||||
| 			        (data.is_active == true) ? tr = add_tr.replace('<td>status</td>', '<td><i class="fa fa-circle text-navy"></i></td>'): tr = add_tr.replace('<td>status</td>', '<td><i class="fa fa-circle text-danger"></i></td>'); | ||||
| 			        $('#asset_list_table > tbody').append(tr); | ||||
| 
 | ||||
| 		        } | ||||
| 	        }); | ||||
|         }); | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function objectDelete(obj, name, url, data) { | ||||
|     function doDelete() { | ||||
|         var body = data; | ||||
|         var success = function() { | ||||
|             swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success"); | ||||
|             $(obj).parent().parent().remove(); | ||||
|         }; | ||||
|         var fail = function() { | ||||
|             swal("Failed", "Delete"+"[ "+name+" ]"+"failed", "error"); | ||||
|         }; | ||||
|         APIUpdateAttr({ | ||||
|             url: url, | ||||
|             body: JSON.stringify(body), | ||||
|             method: 'PATCH', | ||||
|             success: success, | ||||
|             error: fail | ||||
|         }); | ||||
|     } | ||||
|     swal({ | ||||
|         title: 'Are you sure delete ?', | ||||
|         text: " [" + name + "] ", | ||||
|         type: "warning", | ||||
|         showCancelButton: true, | ||||
|         cancelButtonText: 'Cancel', | ||||
|         confirmButtonColor: "#DD6B55", | ||||
|         confirmButtonText: 'Confirm', | ||||
|         closeOnConfirm: false | ||||
|     }, function () { | ||||
|         doDelete() | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function updateAssetGroupSystemUsers(system_users) { | ||||
| 	var the_url = "{% url 'api-assets:asset-groups-update-systemusers' pk=asset_group.id %}"; | ||||
|     var body = { | ||||
|         system_users: Object.assign([], system_users) | ||||
|     }; | ||||
|     var success = function(data) { | ||||
|         $('.select2-selection__rendered').empty(); | ||||
|         $('#groups_selected').val(''); | ||||
|         $.map(jumpserver.system_users_selected, function(system_user, index) { | ||||
|             $('#opt_' + index).remove(); | ||||
|             $('.system-user-table tbody').append( | ||||
|                 '<tr>' + | ||||
|                 '<td><b class="bdg_group" data-sid="' + index + '">' + system_user + '</b></td>' + | ||||
|                 '<td><button class="btn btn-danger btn-xs pull-right btn_leave_group" type="button"><i class="fa fa-minus"></i></button></td>' + | ||||
|                 '</tr>' | ||||
|             ) | ||||
|         }); | ||||
|         jumpserver.system_users_selected = {}; | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| Array.prototype.remove = function(val) { | ||||
| 	var index = this.indexOf(val); | ||||
| 		if (index > -1) { | ||||
| 		this.splice(index, 1); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| Array.prototype.unique = function(){ | ||||
| 	var res = []; | ||||
| 	var json = {}; | ||||
|  	for(var i = 0; i < this.length; i++){ | ||||
|   		if(!json[this[i]]){ | ||||
|    			res.push(this[i]); | ||||
|    			json[this[i]] = 1; | ||||
|   		} | ||||
|  	} | ||||
|  	return res; | ||||
| }; | ||||
| 
 | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2() | ||||
| 	.on("select2:select", function (evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		jumpserver.assets_selected[data.id] = data.text; | ||||
| 		jumpserver.system_users_selected[data.id] = data.text; | ||||
| 	}) | ||||
| 	.on('select2:unselect', function(evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		delete jumpserver.assets_selected[data.id]; | ||||
| 		delete jumpserver.system_users_selected[data.id] | ||||
| 	}); | ||||
| 
 | ||||
| 	var options = { | ||||
| 		ele: $('#asset_list_table'), | ||||
| 		buttons: [], | ||||
| 		order: [], | ||||
|                 select: [], | ||||
| 		columnDefs: [ | ||||
|                     {targets: 1, createdCell: function (td, cellData, rowData) { | ||||
|                         var detail_btn = '<a href="{% url "perms:asset-permission-detail" pk=99991937 %}">' + cellData + '</a>'; | ||||
| 			{targets: 0, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}" data-aid="'+rowData.id+'">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
|                     {targets: 2, createdCell: function (td, cellData, rowData) { | ||||
|                         var dataLength = cellData.length; | ||||
|                         $(td).html(dataLength); | ||||
|                     }}, | ||||
|                     {targets: 3, createdCell: function (td, cellData, rowData) { | ||||
|                         var dataLength = cellData.length; | ||||
|                         $(td).html(dataLength); | ||||
|                     }}, | ||||
|                     {targets: 4, createdCell: function (td, cellData, rowData) { | ||||
|                         var dataLength = cellData.length; | ||||
|                         $(td).html(dataLength); | ||||
|                     }}, | ||||
|                     {targets: 5, createdCell: function (td, cellData) { | ||||
| 			{targets: 4, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-times text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-check text-navy"></i>') | ||||
| 				} | ||||
| 			}}, | ||||
|                     {targets: 6, createdCell: function (td, cellData, rowData) { | ||||
|                         var btn = '<button class="btn btn-danger btn-xs btn_del_permission disabled" id=99991937 type="button" style="float: right;"><i class="fa fa-minus"></i></button>'; | ||||
|                         if (rowData.is_inherited) { | ||||
|                             $(td).html(btn) | ||||
|                         } else { | ||||
|                             btn = btn.replace('99991937', cellData); | ||||
|                             $(td).html(btn.replace('disabled', '')); | ||||
|                         } | ||||
| 			{targets: 5, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', rowData.id); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-aid="99991937">{% trans "Remove" %}</a>'.replace('99991937', rowData.id); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 		], | ||||
|                 ajax_url: '{% url "api-perms:asset-permission-list" %}?user={{ user.id }}', | ||||
|                 columns: [{data: function(){return ""}}, {data: "name" }, {data: "assets" }, {data: "asset_groups"}, | ||||
|                     {data: "system_users"}, {data: "is_active"}, {data: "id"}] | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}?asset_group_id={{ asset_group.id }}', | ||||
| 		columns: [{data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
| 			{data: "type" }, {data: "is_active" }, {data: "id"}], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
|         }) | ||||
|     </script> | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-asset-add-groups', function () { | ||||
| 	if (Object.keys(jumpserver.assets_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	jumpserver.system_users_selected = {}; | ||||
| 	var $data_table = $("#asset_list_table").DataTable(); | ||||
| 	var assets = []; | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:asset-list" %}?asset_group_id={{ asset_group.id }}', | ||||
| 		method: 'GET', | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for(var i in result){ | ||||
| 				if (!isNaN(parseInt(result[i]['id']))) { | ||||
| 					assets.push(parseInt(result[i]['id'])) | ||||
| 				} | ||||
| 			} | ||||
| 			$.map(jumpserver.assets_selected, function(value, index) { | ||||
| 				assets.push(parseInt(index)); | ||||
| 			}); | ||||
| 			assets.unique(); | ||||
| 			var the_url = "{% url 'api-assets:asset-groups-update' pk=asset_group.id %}"; | ||||
| 			var body = {"assets": assets}; | ||||
| 			APIUpdateAttr({ | ||||
| 				url: the_url, | ||||
| 	            body: JSON.stringify(body), | ||||
| 	            method: 'PATCH' | ||||
| 			}); | ||||
| {#			TODO: reflash the table and reset the jumpserver variables #} | ||||
| {#			window.location.href='{% url "assets:asset-group-detail" pk=asset_group.id %}';#} | ||||
| 
 | ||||
| 		} | ||||
| 	}); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_asset_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var the_url = "{% url 'api-assets:asset-groups-update' pk=asset_group.id %}"; | ||||
| 	var name = $(this).closest("tr").find(":nth-child(1) > a").html(); | ||||
| 	var assets = []; | ||||
| 	$('#asset_list_table > tbody > tr').map(function () { | ||||
| 		assets.push(parseInt($(this).closest("tr").find(":nth-child(1) > a").attr("data-aid"))) | ||||
| 	}); | ||||
| 	var delete_asset_id = $(this).data('aid'); | ||||
| 	assets.remove(delete_asset_id); | ||||
| 	var data = {"assets": assets}; | ||||
| 	objectDelete($this, name, the_url, data); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-asset-add-groups-system-users', function () { | ||||
| 	if (Object.keys(jumpserver.system_users_selected).length === 0) { | ||||
|         return false; | ||||
| 	} | ||||
| 	jumpserver.assets_selected = {}; | ||||
| 	var system_users = $('.bdg_system_user').map(function() { | ||||
| 		return $(this).data('sid'); | ||||
| 	}).get(); | ||||
| 	$.map(jumpserver.system_users_selected, function(value, index) { | ||||
| 		system_users.push(parseInt(index)); | ||||
| 		$('#opt_' + index).remove(); | ||||
| 	}); | ||||
| 	system_users.unique(); | ||||
| 	updateAssetGroupSystemUsers(system_users); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_leave_asset_group', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $tr = $this.closest('tr'); | ||||
| 	var $badge = $tr.find('.bdg_system_user'); | ||||
| 	var sid = $badge.data('sid'); | ||||
| 	var name = $badge.html() || $badge.text(); | ||||
| 	$('system-user-table').append( | ||||
| 		'<option value="' + sid + '" id="opt_' + sid + '">' + name + '</option>' | ||||
| 	); | ||||
| 	$tr.remove(); | ||||
| 	var system_users = $('.bdg_system_user').map(function () { | ||||
| 		return $(this).data('sid'); | ||||
| 	}).get(); | ||||
| 	updateAssetGroupSystemUsers(system_users) | ||||
| }) | ||||
| 
 | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -21,6 +21,20 @@ | |||
|     <tbody> | ||||
|     </tbody> | ||||
| </table> | ||||
| <div id="actions" class="hide"> | ||||
|     <div class="input-group"> | ||||
|         <select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
|             <option value="delete">{% trans 'Delete selected' %}</option> | ||||
|             <option value="update">{% trans 'Update selected' %}</option> | ||||
|         </select> | ||||
|         <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
|             <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary"> | ||||
|              {% trans 'Submit' %} | ||||
|             </button> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| {% include 'assets/_asset_group_bulk_update_modal.html' %} | ||||
| {% endblock %} | ||||
| {% block content_bottom_left %}{% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|  | @ -43,17 +57,125 @@ $(document).ready(function(){ | |||
|                 $(td).html(update_btn + del_btn) | ||||
|              }}], | ||||
|         ajax_url: '{% url "api-assets:asset-group-list" %}', | ||||
|         columns: [{data: "id"}, {data: "name" }, {data: "assets_amount" }, {data: "comment" }, {data: "id"}] | ||||
|         columns: [{data: "id"}, {data: "name" }, {data: "assets_amount" }, {data: "comment" }, {data: "id"}], | ||||
| 	    op_html: $('#actions').html() | ||||
|     }; | ||||
|     jumpserver.initDataTable(options); | ||||
| }) | ||||
| 	.on('click', '.btn_asset_group_delete', function () { | ||||
| 
 | ||||
| .on('click', '.btn_asset_group_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $('#asset_groups_list_table').DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:asset-group-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $('#slct_bulk_update').val(); | ||||
| 	var $data_table = $('#asset_groups_list_table').DataTable(); | ||||
| 	var id_list = []; | ||||
|     var plain_id_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (id_list === []) { | ||||
|         return false; | ||||
|     } | ||||
|     var the_url = '{% url "api-assets:asset-group-list" %}'; | ||||
|     console.log(plain_id_list); | ||||
|     console.log(the_url); | ||||
|     function doDelete() { | ||||
|         swal({ | ||||
|             title: "{% trans 'Are you sure?' %}", | ||||
|             text: "{% trans 'This will delete the selected groups !!!' %}", | ||||
|             type: "warning", | ||||
|             showCancelButton: true, | ||||
|             confirmButtonColor: "#DD6B55", | ||||
|             confirmButtonText: "{% trans 'Confirm' %}", | ||||
|             closeOnConfirm: false | ||||
|         }, function() { | ||||
|             var success = function() { | ||||
|                 var msg = "{% trans 'Group Deleted.' %}"; | ||||
|                 swal("{% trans 'Group Delete' %}", msg, "success"); | ||||
|                 $('#asset_groups_list_table').DataTable().ajax.reload(); | ||||
|             }; | ||||
|             var fail = function() { | ||||
|                 var msg = "{% trans 'Group Deleting failed.' %}"; | ||||
|                 swal("{% trans 'Group Delete' %}", msg, "error"); | ||||
|             }; | ||||
|             var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); | ||||
|             APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail}); | ||||
|             $data_table.ajax.reload(); | ||||
|             jumpserver.checked = false; | ||||
|         }); | ||||
|     } | ||||
| 	function doUpdate() { | ||||
| 		$('#asset_group_bulk_update_modal').modal('show'); | ||||
| 	} | ||||
|     switch(action) { | ||||
|         case 'delete': | ||||
|             doDelete(); | ||||
|             break; | ||||
|         case 'update': | ||||
|             doUpdate(); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_asset_group_bulk_update', function () { | ||||
| 	var json_data = $("#fm_asset_group_bulk_update").serializeObject(); | ||||
| 	var body = {}; | ||||
|     body.enable_otp = (json_data.enable_otp === 'on')? true: false; | ||||
|     if (json_data.type != '') { | ||||
|         body.type = json_data.type; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.assets != undefined) { | ||||
|         body.assets = json_data.assets; | ||||
|     } | ||||
|     if (typeof body.assets === 'string') { | ||||
|         body.assets = [parseInt(body.assets)] | ||||
|     } else if(typeof body.assets === 'array') { | ||||
|         var new_assets = body.assets.map(Number); | ||||
|         body.assets = new_assets; | ||||
|     } | ||||
| 
 | ||||
| 	if (json_data.system_users != undefined) { | ||||
|     	body.system_users = json_data.system_users; | ||||
| 	} | ||||
| 	if (typeof body.system_users === 'string') { | ||||
|     	body.system_users = [parseInt(body.system_users)]; | ||||
| 	} else if (typeof body.system_users === 'array') { | ||||
|     	var new_system_users = body.system_users.map(Number); | ||||
|     	body.system_users = new_system_users; | ||||
| 	} | ||||
| 
 | ||||
| 	var post_list = []; | ||||
|     var $data_table = $('#asset_groups_list_table').DataTable() | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         var content = Object.assign({id: this.data().id}, body); | ||||
|         post_list.push(content); | ||||
|     }); | ||||
|     if (post_list === []) { | ||||
|         return false | ||||
|     } | ||||
|     var the_url = '{% url "api-assets:asset-group-list" %}'; | ||||
|     var success = function() { | ||||
|         var msg = "{% trans 'The selected asset groups has been updated successfully.' %}"; | ||||
|         swal("{% trans 'AssetGroup Updated' %}", msg, "success"); | ||||
|         $('#asset_groups_list_table').DataTable().ajax.reload(); | ||||
|         jumpserver.checked = false; | ||||
|     }; | ||||
| {#	console.log(JSON.stringify(post_list));#} | ||||
|     APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(post_list), success: success}); | ||||
|     $('#asset_group_bulk_update_modal').modal('hide'); | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -72,6 +72,7 @@ | |||
|             <option value="delete">{% trans 'Delete selected' %}</option> | ||||
|             <option value="update">{% trans 'Update selected' %}</option> | ||||
|             <option value="deactive">{% trans 'Deactive selected' %}</option> | ||||
| 	        <option value="active">{% trans 'Active' %}</option> | ||||
|         </select> | ||||
|         <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
|             <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary"> | ||||
|  | @ -81,12 +82,13 @@ | |||
|     </div> | ||||
| </div> | ||||
| {% include 'assets/_asset_import_modal.html' %} | ||||
| {% include 'assets/_asset_bulk_update_modal.html' %} | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block custom_foot_js %} | ||||
| <script src="{% static 'js/jquery.form.min.js' %}"></script> | ||||
| <script type="text/javascript"> | ||||
|     window.onload = function (){ | ||||
| window.onload = function (){ | ||||
|         var tag_on = document.getElementsByName("tag_on"); | ||||
|         var oDiv = document.getElementById("ydxbd"); | ||||
|         if(tag_on.length > 0){ | ||||
|  | @ -94,16 +96,16 @@ | |||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     function tagShow() { | ||||
| function tagShow() { | ||||
| 	var oDiv = document.getElementById("ydxbd"); | ||||
| 	if (oDiv.style.display == 'none'){ | ||||
| 		oDiv.style.display = "block"; | ||||
| 	}else{ | ||||
| 		oDiv.style.display = "none"; | ||||
| 	} | ||||
|     }  //onload; | ||||
| }  //onload; | ||||
| 
 | ||||
|     $(document).ready(function(){ | ||||
| $(document).ready(function(){ | ||||
| 	var options = { | ||||
| 		ele: $('#asset_list_table'), | ||||
| 		columnDefs: [ | ||||
|  | @ -129,7 +131,6 @@ | |||
| 				var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 
 | ||||
| 			}} | ||||
| 		], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}', | ||||
|  | @ -139,13 +140,13 @@ | |||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	var table = jumpserver.initDataTable(options); | ||||
| 
 | ||||
| 	$('.btn_export').click(function () { | ||||
| 		var assets = []; | ||||
| 		var rows = table.rows('.selected').data(); | ||||
| 		$.each(rows, function (index, obj) { | ||||
| 			assets.push(obj.id) | ||||
| 		}); | ||||
| 		console.log(assets); | ||||
| 		$.ajax({ | ||||
| 			url: "{% url "assets:asset-export" %}", | ||||
| 			method: 'POST', | ||||
|  | @ -159,7 +160,6 @@ | |||
| 			} | ||||
| 		}) | ||||
| 	}); | ||||
| 
 | ||||
|  	$('#btn_asset_import').click(function() { | ||||
| 		var $form = $('#fm_asset_import'); | ||||
| 		$form.find('.help-block').remove(); | ||||
|  | @ -179,15 +179,150 @@ | |||
| 		} | ||||
| 		$form.ajaxSubmit({success: success}); | ||||
| 	}) | ||||
| }) | ||||
| 
 | ||||
|     }) | ||||
| 	    .on('click', '.btn_asset_delete', function () { | ||||
| .on('click', '.btn_asset_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $("#asset_list_table").DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:asset-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 
 | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $('#slct_bulk_update').val(); | ||||
| 	var $data_table = $('#asset_list_table').DataTable(); | ||||
| 	var id_list = []; | ||||
|     var plain_id_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (plain_id_list.length == 0) { | ||||
|         return false; | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:asset-list' %}"; | ||||
|     function doDeactive() { | ||||
|         var body = $.each(id_list, function(index, asset_object) { | ||||
|             asset_object['is_active'] = false; | ||||
|         }); | ||||
|         APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(body)}); | ||||
|         $data_table.ajax.reload(); | ||||
|         jumpserver.checked = false; | ||||
|     } | ||||
|     function doActive() { | ||||
|         var body = $.each(id_list, function(index, asset_object) { | ||||
|             asset_object['is_active'] = true; | ||||
|         }); | ||||
|         APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(body)}); | ||||
|         $data_table.ajax.reload(); | ||||
|         jumpserver.checked = false; | ||||
|     } | ||||
|     function doDelete() { | ||||
|         swal({ | ||||
|             title: "{% trans 'Are you sure?' %}", | ||||
|             text: "{% trans 'This will delete the selected assets !!!' %}", | ||||
|             type: "warning", | ||||
|             showCancelButton: true, | ||||
|             confirmButtonColor: "#DD6B55", | ||||
|             confirmButtonText: "{% trans 'Confirm' %}", | ||||
|             closeOnConfirm: false | ||||
|         }, function() { | ||||
|             var success = function() { | ||||
|                 var msg = "{% trans 'Asset Deleted.' %}"; | ||||
|                 swal("{% trans 'Asset Delete' %}", msg, "success"); | ||||
|                 $('#asset_list_table').DataTable().ajax.reload(); | ||||
|             }; | ||||
|             var fail = function() { | ||||
|                 var msg = "{% trans 'Asset Deleting failed.' %}"; | ||||
|                 swal("{% trans 'Asset Delete' %}", msg, "error"); | ||||
|             }; | ||||
|             var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); | ||||
|             APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail}); | ||||
|             $data_table.ajax.reload(); | ||||
|             jumpserver.checked = false; | ||||
|         }); | ||||
|     } | ||||
|     function doUpdate() { | ||||
|         $('#asset_bulk_update_modal').modal('show'); | ||||
|     } | ||||
|     switch(action) { | ||||
|         case 'deactive': | ||||
|             doDeactive(); | ||||
|             break; | ||||
|         case 'delete': | ||||
|             doDelete(); | ||||
|             break; | ||||
|         case 'update': | ||||
|             doUpdate(); | ||||
|             break; | ||||
|         case 'active': | ||||
|             doActive(); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_asset_bulk_update', function () { | ||||
| 	var json_data = $("#fm_asset_bulk_update").serializeObject(); | ||||
| 	var body = {}; | ||||
|     body.enable_otp = (json_data.enable_otp === 'on')? true: false; | ||||
|     if (json_data.type != '') { | ||||
|         body.type = json_data.type; | ||||
|     } | ||||
|     if (json_data.groups != undefined) { | ||||
|         body.groups = json_data.groups; | ||||
|     } | ||||
|     if (typeof body.groups === 'string') { | ||||
|         body.groups = [parseInt(body.groups)] | ||||
|     } else if(typeof body.groups === 'array') { | ||||
|         var new_groups = body.groups.map(Number); | ||||
|         body.groups = new_groups; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.system_users != undefined) { | ||||
|     	body.system_users = json_data.system_users; | ||||
|     } | ||||
|     if (typeof body.system_users === 'string') { | ||||
|     	body.system_users = [parseInt(body.system_users)] | ||||
|     } else if(typeof body.system_users === 'array') { | ||||
|     	var new_users = body.system_users.map(Number); | ||||
|     	body.system_users = new_users; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.tags != undefined) { | ||||
|     	body.tags = json_data.tags; | ||||
|     } | ||||
|     if (typeof body.tags == 'string') { | ||||
|     	body.tags = [parseInt(body.tags)]; | ||||
|     } else if (typeof body.tags === 'array') { | ||||
|     	var new_tags = body.tags.map(Number); | ||||
|     	body.tags = new_tags; | ||||
|     } | ||||
| 
 | ||||
|     var $data_table = $('#asset_list_table').DataTable(); | ||||
|     var post_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         var content = Object.assign({id: this.data().id}, body); | ||||
|         post_list.push(content); | ||||
|     }); | ||||
|     if (post_list === []) { | ||||
|         return false | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:asset-list' %}"; | ||||
|     var success = function() { | ||||
|         var msg = "{% trans 'The selected assets has been updated successfully.' %}"; | ||||
|         swal("{% trans 'Asset Updated' %}", msg, "success"); | ||||
|         $('#asset_list_table').DataTable().ajax.reload(); | ||||
|         jumpserver.checked = false; | ||||
|     }; | ||||
|     console.log(JSON.stringify(post_list)); | ||||
|     console.log(the_url); | ||||
| {#    APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(post_list), success: success});#} | ||||
|     $('#asset_bulk_update_modal').modal('hide'); | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -77,80 +77,27 @@ | |||
|                                     </div> | ||||
|                                 </div> | ||||
|                                 <div class="ibox-content"> | ||||
|                                     <table class="table table-hover"> | ||||
| 									<table class="table table-striped table-bordered table-hover " id="tag_assets_table" > | ||||
|                                         <thead> | ||||
|                                             <tr> | ||||
|                                                 <th>{% trans 'Hostname' %}</th> | ||||
|                                                 <th>{% trans 'IP' %}</th> | ||||
|                                                 <th>{% trans 'Port' %}</th> | ||||
|                                                 <th>{% trans 'Alive' %}</th> | ||||
|                                                 <th>{% trans 'Type' %}</th> | ||||
|                                                 <th>{% trans 'Valid' %}</th> | ||||
| 												<th>{% trans 'Action' %}</th> | ||||
|                                             </tr> | ||||
|                                         </thead> | ||||
|                                         <tbody> | ||||
|                                             {% for asset in page_obj %} | ||||
|                                             <tr> | ||||
|                                                 <td>{{ asset.hostname }}</td> | ||||
|                                                 <td>{{ asset.ip }}</td> | ||||
|                                                 <td>{{ asset.port }}</td> | ||||
|                                                 <td>Alive</td> | ||||
|                                             </tr> | ||||
|                                             {% endfor %} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                     <div class="row"> | ||||
|                                         {% include '_pagination.html' %} | ||||
|                                     </div> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-sm-5" style="padding-left: 0;padding-right: 0"> | ||||
|                             <div class="panel panel-primary"> | ||||
|                                 <div class="panel-heading"> | ||||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Associate system user' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table"> | ||||
|                                         <tbody> | ||||
|                                         <tr class="no-borders-tr"> | ||||
|                                             <td width="50%">{% trans 'repush system user' %}:</td> | ||||
|                                             <td> | ||||
|                                                 <span style="float: right"> | ||||
|                                                     <button class="btn btn-danger btn-xs" type="button"><i class="fa fa-refresh"></i></button> | ||||
|                                                 </span> | ||||
|                                             </td> | ||||
|                                         </tr> | ||||
|                                         <form> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select system user' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for group in groups %} | ||||
|                                                             <option value="{{ group.id }}">{{ group.name }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm">{% trans 'Associate' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|                                         {% for group in user.groups.all %} | ||||
|                                         <tr> | ||||
|                                             <td ><b>{{ group.name }}</b></td> | ||||
|                                             <td> | ||||
|                                                 <button class="btn btn-danger btn-xs" type="button" style="float: right;"><i class="fa fa-minus"></i></button> | ||||
|                                             </td> | ||||
|                                         </tr> | ||||
|                                         {% endfor %} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                 </div> | ||||
|                             </div> | ||||
| 
 | ||||
|                             <div class="panel panel-info"> | ||||
|                                 <div class="panel-heading"> | ||||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Add asset to this group' %} | ||||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Add asset to this tag' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table"> | ||||
|  | @ -158,27 +105,19 @@ | |||
|                                         <form> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select asset user' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for group in groups %} | ||||
|                                                             <option value="{{ group.id }}">{{ group.name }}</option> | ||||
|                                                     <select data-placeholder="{% trans 'Select asset' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for asset in assets_remain %} | ||||
|                                                             <option value="{{ asset.id }}">{{ asset.ip }}:{{ asset.port }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm">{% trans 'Add' %}</button> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm btn-tag-asset-add">{% trans 'Add' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|                                         {% for group in user.groups.all %} | ||||
|                                         <tr> | ||||
|                                             <td ><b>{{ group.name }}</b></td> | ||||
|                                             <td> | ||||
|                                                 <button class="btn btn-danger btn-xs" type="button" style="float: right;"><i class="fa fa-minus"></i></button> | ||||
|                                             </td> | ||||
|                                         </tr> | ||||
|                                         {% endfor %} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                 </div> | ||||
|  | @ -194,26 +133,147 @@ | |||
| 
 | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
| {#        function switch_user_status(obj) {#} | ||||
| {#            var status = $(obj).prop('checked');#} | ||||
| {##} | ||||
| {#            $.ajax({#} | ||||
| {#                url: "{% url 'users:user-active-api' pk=user.id %}",#} | ||||
| {#                type: "PUT",#} | ||||
| {#                data: {#} | ||||
| {#                    'is_active': status#} | ||||
| {#                },#} | ||||
| {#                success: function (data, status) {#} | ||||
| {#                    console.log(data)#} | ||||
| {#                },#} | ||||
| {#                error: function () {#} | ||||
| {#                    console.log('error')#} | ||||
| {#                }#} | ||||
| {#            })#} | ||||
| {#        }#} | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
| <script> | ||||
| jumpserver.assets_selected = {}; | ||||
| 
 | ||||
| function updateTagAssets(assets) { | ||||
| 	var the_url = "{% url 'api-assets:tag-update-assets' pk=tag.id %}"; | ||||
|     var body = { | ||||
|         assets: Object.assign([], assets) | ||||
|     }; | ||||
| 	var $data_table = $("#tag_assets_table").DataTable(); | ||||
|     var success = function(data) { | ||||
|         $('.select2-selection__rendered').empty(); | ||||
|         $.map(jumpserver.assets_selected, function(asset_ip, index) { | ||||
| 	        $('#opt_' + index).remove(); | ||||
| 			$data_table.ajax.reload(); | ||||
|         }); | ||||
|         jumpserver.groups_selected = {}; | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
| 	    method: 'PUT', | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| function deleteTagAssets(obj, name, url, data) { | ||||
|     function doDelete() { | ||||
|         var body = data; | ||||
|         var success = function() { | ||||
|             swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success"); | ||||
|             $(obj).parent().parent().remove(); | ||||
|         }; | ||||
|         var fail = function() { | ||||
|             swal("Failed", "Delete"+"[ "+name+" ]"+"failed", "error"); | ||||
|         }; | ||||
|         APIUpdateAttr({ | ||||
|             url: url, | ||||
|             body: JSON.stringify(body), | ||||
|             method: 'PATCH', | ||||
|             success: success, | ||||
|             error: fail | ||||
|         }); | ||||
|     } | ||||
|     swal({ | ||||
|         title: 'Are you sure delete ?', | ||||
|         text: " [" + name + "] ", | ||||
|         type: "warning", | ||||
|         showCancelButton: true, | ||||
|         cancelButtonText: 'Cancel', | ||||
|         confirmButtonColor: "#DD6B55", | ||||
|         confirmButtonText: 'Confirm', | ||||
|         closeOnConfirm: false | ||||
|     }, function () { | ||||
|         doDelete() | ||||
|     }); | ||||
| } | ||||
| Array.prototype.remove = function(val) { | ||||
| 	var index = this.indexOf(val); | ||||
| 		if (index > -1) { | ||||
| 		this.splice(index, 1); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2() | ||||
| 	.on("select2:select", function (evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		jumpserver.assets_selected[data.id] = data.text; | ||||
| 	}) | ||||
|     </script> | ||||
| 	.on('select2:unselect', function(evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		delete jumpserver.assets_selected[data.id]; | ||||
| 	}); | ||||
| 	var options = { | ||||
| 		ele: $('#tag_assets_table'), | ||||
| 		buttons: [], | ||||
| 		order: [], | ||||
| 		columnDefs: [ | ||||
| 			{targets: 0, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}" data-aid="'+rowData.id+'">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 4, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-times text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-check text-navy"></i>') | ||||
| 				} | ||||
| 			}}, | ||||
| 			{targets: 5, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', rowData.id); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-aid="99991937">{% trans "Delete" %}</a>'.replace('99991937', rowData.id); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 
 | ||||
| 			], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}?tag_id={{ tag.id }}', | ||||
| 		columns: [{data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
| 			{data: "type" }, {data: "is_active" }, {data: "id"}], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-tag-asset-add', function () { | ||||
| 	if (Object.keys(jumpserver.assets_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	var assets=[]; | ||||
| 	var $data_table = $("#tag_assets_table").DataTable(); | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:asset-list" %}', | ||||
| 		method: 'GET', | ||||
| 		data: {"tag_id": {{ tag.id }}}, | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for(var i in result){ | ||||
| 				if (!isNaN(parseInt(result[i]['id']))) { | ||||
| 					assets.push(parseInt(result[i]['id'])) | ||||
| 				} | ||||
| 			} | ||||
| 			$.map(jumpserver.assets_selected, function(value, index) { | ||||
| 				assets.push(parseInt(index)); | ||||
| 			}); | ||||
| 			updateTagAssets(assets); | ||||
| 			$data_table.ajax().reload(); | ||||
| 		} | ||||
| 	}) | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_asset_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var the_url = "{% url 'api-assets:tag-update-assets' pk=tag.id %}"; | ||||
| 	var name = $(this).closest("tr").find(":nth-child(1) > a").html(); | ||||
| 	var assets = []; | ||||
| 	$('#tag_assets_table > tbody > tr').map(function () { | ||||
| 		assets.push(parseInt($(this).closest("tr").find(":nth-child(1) > a").attr("data-aid"))) | ||||
| 	}); | ||||
| 	var delete_asset_id = $(this).data('aid'); | ||||
| 	assets.remove(delete_asset_id); | ||||
| 	var data = {"assets": assets}; | ||||
| 	deleteTagAssets($this, name, the_url, data); | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -1,56 +1,126 @@ | |||
| {% extends '_base_list.html' %} | ||||
| {% load i18n %} | ||||
| {% load common_tags %} | ||||
| {% block content_left_head %} | ||||
|     <a href="{% url 'assets:asset-tag-create' %}" class="btn btn-sm btn-primary "> {% trans "Create tag" %}</a> | ||||
| {% load i18n static %} | ||||
| {#{% load common_tags %}#} | ||||
| {% 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 table_head %} | ||||
|     <th class="text-center"> | ||||
|         <input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')"> | ||||
|     </th> | ||||
|     <th class="text-center"><a href="{% url 'assets:asset-tag-list' %}?sort=name">{% trans 'Tag Name' %}</a></th> | ||||
| {#{% block content_left_head %}#} | ||||
| {#    <a href="{% url 'assets:asset-tag-create' %}" class="btn btn-sm btn-primary "> {% trans "Create tag" %}</a>#} | ||||
| {#{% endblock %}#} | ||||
| {#{% block table_head %}#} | ||||
| {#    <th class="text-center">#} | ||||
| {#        <input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')">#} | ||||
| {#    </th>#} | ||||
| {#    <th class="text-center"><a href="{% url 'assets:asset-tag-list' %}?sort=name">{% trans 'Tag Name' %}</a></th>#} | ||||
| {#    <th class="text-center">{% trans 'Asset num' %}</th>#} | ||||
| {#    <th class="text-center"></th>#} | ||||
| {#{% endblock %}#} | ||||
| {#{% block table_body %}#} | ||||
| {#     {% for asset_tag in asset_tags_list %}#} | ||||
| {#         <tr class="gradeX">#} | ||||
| {#             <td class="text-center">#} | ||||
| {#                 <input type="checkbox" name="checked" value="{{ asset_tag.id }}">#} | ||||
| {#             </td>#} | ||||
| {#             <td class="text-center">#} | ||||
| {#                 <a href="{% url 'assets:asset-tag-detail' pk=asset_tag.id %}">#} | ||||
| {#                     {{ asset_tag.name }}#} | ||||
| {#                 </a>#} | ||||
| {#             </td>#} | ||||
| {#             <td class="text-center">{{ asset_tag.asset_set.count }}</td>#} | ||||
| {#             <td class="text-center">#} | ||||
| {#                 <a href="{% url 'assets:asset-tag-update' pk=asset_tag.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>#} | ||||
| {#                 <a onclick="objectDelete(this,'{{ asset_tag.name }}','{% url 'assets:asset-tag-delete' asset_tag.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>#} | ||||
| {#             </td>#} | ||||
| {#         </tr>#} | ||||
| {#     {% endfor %}#} | ||||
| {#{% endblock %}#} | ||||
| {#{% block content_bottom_left %}#} | ||||
| {#    <form id="" method="get" action="" class=" mail-search">#} | ||||
| {#        <div class="input-group">#} | ||||
| {#            <select class="form-control m-b" style="width: auto">#} | ||||
| {#                <option>{% trans 'Delete selected' %}</option>#} | ||||
| {#                <option>{% trans 'Update selected' %}</option>#} | ||||
| {#                <option>{% trans 'Deactive selected' %}</option>#} | ||||
| {#                <option>{% trans 'Export selected' %}</option>#} | ||||
| {#            </select>#} | ||||
| {#            <div class="input-group-btn pull-left" style="padding-left: 5px;">#} | ||||
| {#                <button id='search_btn' type="submit" style="height: 32px;"  class="btn btn-sm btn-primary">#} | ||||
| {#                 {% trans 'Submit' %}#} | ||||
| {#                </button>#} | ||||
| {#            </div>#} | ||||
| {#        </div>#} | ||||
| {#   </form>#} | ||||
| {#{% endblock %}#} | ||||
| {% block table_search %}{% endblock %} | ||||
| {% block table_container %} | ||||
| <div class="uc pull-left m-l-5 m-r-5"> | ||||
|     <a href="{% url "assets:asset-tag-create" %}" class="btn btn-sm btn-primary"> {% trans "Create Tag" %} </a> | ||||
| </div> | ||||
| <table class="table table-striped table-bordered table-hover " id="tag_list_table" > | ||||
|     <thead> | ||||
|         <tr> | ||||
|             <th class="text-center"><input type="checkbox" class="ipt_check_all"></th> | ||||
|             <th class="text-center">{% trans 'TagName' %}</th> | ||||
|             <th class="text-center">{% trans 'Asset num' %}</th> | ||||
|     <th class="text-center"></th> | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block table_body %} | ||||
| 
 | ||||
|      {% for asset_tag in asset_tags_list %} | ||||
|          <tr class="gradeX"> | ||||
|              <td class="text-center"> | ||||
|                  <input type="checkbox" name="checked" value="{{ asset_tag.id }}"> | ||||
|              </td> | ||||
|              <td class="text-center"> | ||||
|                  <a href="{% url 'assets:asset-tag-detail' pk=asset_tag.id %}"> | ||||
|                      {{ asset_tag.name }} | ||||
|                  </a> | ||||
|              </td> | ||||
|              <td class="text-center">{{ asset_tag.asset_set.count }}</td> | ||||
|              <td class="text-center"> | ||||
|                  <a href="{% url 'assets:asset-tag-update' pk=asset_tag.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a> | ||||
|                  <a onclick="objectDelete(this,'{{ asset_tag.name }}','{% url 'assets:asset-tag-delete' asset_tag.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a> | ||||
|              </td> | ||||
|             <th class="text-center">{% trans 'Action' %}</th> | ||||
|         </tr> | ||||
|      {% endfor %} | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block content_bottom_left %} | ||||
|     <form id="" method="get" action="" class=" mail-search"> | ||||
|     </thead> | ||||
|     <tbody> | ||||
|     </tbody> | ||||
| </table> | ||||
| <div id="actions" class="hide"> | ||||
|     <div class="input-group"> | ||||
|             <select class="form-control m-b" style="width: auto"> | ||||
|                 <option>{% trans 'Delete selected' %}</option> | ||||
|                 <option>{% trans 'Update selected' %}</option> | ||||
|                 <option>{% trans 'Deactive selected' %}</option> | ||||
|                 <option>{% trans 'Export selected' %}</option> | ||||
|         <select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
|             <option value="delete">{% trans 'Delete selected' %}</option> | ||||
|             <option value="update">{% trans 'Update selected' %}</option> | ||||
|         </select> | ||||
| 
 | ||||
|         <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
|                 <button id='search_btn' type="submit" style="height: 32px;"  class="btn btn-sm btn-primary"> | ||||
|             <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary"> | ||||
|              {% trans 'Submit' %} | ||||
|             </button> | ||||
|         </div> | ||||
| 
 | ||||
|     </div> | ||||
|    </form> | ||||
| </div> | ||||
| 
 | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block custom_foot_js %} | ||||
| <script src="{% static 'js/jquery.form.min.js' %}"></script> | ||||
| <script type="text/javascript"> | ||||
| $(document).ready(function () { | ||||
| 	var options = { | ||||
| 		ele: $("#tag_list_table"), | ||||
| 		columnDefs:[ | ||||
| 			{targets: 1, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url 'assets:asset-tag-detail' pk=99991937 %}">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 3, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url 'assets:asset-tag-detail' pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_tag_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 		], | ||||
| 		ajax_url: '{% url "api-assets:asset-tag-list" %}', | ||||
| 		columns: [{data: function(){return ""}}, {data: "name" }, {data: "assets_amount" },{data: "id"}] | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_tag_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $('#tag_list_table').DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:asset-tag-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| {% endblock %} | ||||
|  | @ -7,6 +7,9 @@ | |||
| {% 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> | ||||
| 	<style type="text/css"> | ||||
| 
 | ||||
| 	</style> | ||||
| {% endblock %} | ||||
| {% block content %} | ||||
|     <div class="wrapper wrapper-content animated fadeInRight"> | ||||
|  | @ -42,6 +45,7 @@ | |||
|                                         </a> | ||||
|                                     </div> | ||||
|                                 </div> | ||||
| 
 | ||||
|                                 <div class="ibox-content"> | ||||
|                                     <table class="table table-striped table-bordered table-hover " id="idc_assets_table" > | ||||
|                                         <thead> | ||||
|  | @ -59,13 +63,27 @@ | |||
|                                         <tbody> | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
| 
 | ||||
| 	                                <div id="actions" class="hide"> | ||||
| 									    <div class="input-group"> | ||||
| 									        <select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
| 									            <option value="delete">{% trans 'Delete selected' %}</option> | ||||
| 									        </select> | ||||
| 									        <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
| 									            <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-warning"> | ||||
| 									             {% trans 'Submit' %} | ||||
| 									            </button> | ||||
| 									        </div> | ||||
| 									    </div> | ||||
| 									</div> | ||||
| 
 | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-sm-5" style="padding-left: 0;padding-right: 0"> | ||||
|                             <div class="panel panel-primary"> | ||||
|                                 <div class="panel-heading"> | ||||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Attach to assets ' %} | ||||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Attach assets to IDC ' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table"> | ||||
|  | @ -75,14 +93,14 @@ | |||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select asset' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for asset in assets_remain %} | ||||
|                                                             <option value="{{ asset.id }}">{{ asset.ip}}:{{ asset.port }}</option> | ||||
|                                                             <option value="{{ asset.id }}" id="opt_{{ asset.id }}">{{ asset.ip}}:{{ asset.port }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm">{% trans 'Attach' %}</button> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm btn-asset-attach">{% trans 'Attach Assets' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|  | @ -96,19 +114,77 @@ | |||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
| {% include 'assets/_asset_bulk_update_modal.html' %} | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
| <script src="{% static 'js/jquery.form.min.js' %}"></script> | ||||
| <script> | ||||
| 
 | ||||
| jumpserver.assets_selected = {}; | ||||
| 
 | ||||
| Array.prototype.remove = function(val) { | ||||
| 	var index = this.indexOf(val); | ||||
| 		if (index > -1) { | ||||
| 		this.splice(index, 1); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| function updateIDCAssets(assets) { | ||||
|     var the_url = "{% url 'api-assets:idc-update-assets' pk=idc.id %}"; | ||||
|     var body = { | ||||
|         assets: Object.assign([], assets) | ||||
|     }; | ||||
| 	var $data_table = $("#idc_assets_table").DataTable(); | ||||
|     var success = function(data) { | ||||
|         $('.select2-selection__rendered').empty(); | ||||
|         $.map(jumpserver.assets_selected, function(asset_ip, index) { | ||||
| 	        $('#opt_' + index).remove(); | ||||
| 			$data_table.ajax.reload(); | ||||
|         }); | ||||
|         jumpserver.groups_selected = {}; | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
| 	    method: 'PUT', | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function deleteIDCAssets(assets) { | ||||
| 	var the_url = "{% url 'api-assets:idc-update-assets' pk=idc.id %}"; | ||||
|     var body = { | ||||
|         assets: Object.assign([], assets) | ||||
|     }; | ||||
| 	var $data_table = $("#idc_assets_table").DataTable(); | ||||
| 	var success = function(data) { | ||||
| 		$data_table.ajax.reload(); | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
| 	    method: 'PUT', | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2() | ||||
| 	.on("select2:select", function (evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		jumpserver.assets_selected[data.id] = data.text; | ||||
| 	}) | ||||
| 	.on('select2:unselect', function(evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		delete jumpserver.assets_selected[data.id]; | ||||
| 	}); | ||||
| 	var options = { | ||||
| 		ele: $('#idc_assets_table'), | ||||
| 		buttons: [], | ||||
| 		order: [], | ||||
| 		columnDefs: [ | ||||
| 			{targets: 1, createdCell: function (td, cellData, rowData) { | ||||
|                         var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}">' + cellData + '</a>'; | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}" data-aid="'+rowData.id+'">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 5, createdCell: function (td, cellData) { | ||||
|  | @ -120,9 +196,173 @@ | |||
| 			}}], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}?idc_id={{ idc.id }}', | ||||
| 		columns: [{data: function(){return ""}}, {data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
|                     {data: "type" }, {data: "is_active" }] | ||||
| 			{data: "type" }, {data: "is_active" }], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| 
 | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-asset-attach', function () { | ||||
| 	if (Object.keys(jumpserver.assets_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	var assets=[]; | ||||
| 	var $data_table = $("#idc_assets_table").DataTable(); | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:asset-list" %}', | ||||
| 		method: 'GET', | ||||
| 		data: {"idc_id": {{ idc.id }}}, | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for(var i in result){ | ||||
| 				if (!isNaN(parseInt(result[i]['id']))) { | ||||
| 					assets.push(parseInt(result[i]['id'])) | ||||
| 				} | ||||
| 			} | ||||
| 			$.map(jumpserver.assets_selected, function(value, index) { | ||||
| 				assets.push(parseInt(index)); | ||||
| 			}); | ||||
|     </script> | ||||
| 			updateIDCAssets(assets); | ||||
| 
 | ||||
| 		} | ||||
| 	}); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $("#slct_bulk_update").val(); | ||||
| 	var $data_table = $("#idc_assets_table").DataTable(); | ||||
| 	var id_list = []; | ||||
| 	var plain_id_list = []; | ||||
| 	var assets = []; | ||||
| 	$data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (id_list === []) { | ||||
|         return false; | ||||
|     } | ||||
|     $.ajax({ | ||||
|     	url: '{% url "api-assets:asset-list" %}', | ||||
| 	    data: {"idc_id": {{ idc.id }}}, | ||||
| 	    dataType: 'json', | ||||
| 	    method: 'GET', | ||||
| 	    success: function (result) { | ||||
| 		    for (var i in result) { | ||||
| 		    	if (!isNaN(result[i]['id'])) { | ||||
| 		    		assets.push(result[i]['id']); | ||||
| 			    } | ||||
| 		    } | ||||
| 		    for (var j in plain_id_list) { | ||||
| 		    	assets.remove(plain_id_list[j]) | ||||
| 		    } | ||||
| 		    function doDelete() { | ||||
| 				swal({ | ||||
| 		            title: "{% trans 'Are you sure?' %}", | ||||
| 		            text: "{% trans 'This will delete the selected assets !!!' %}", | ||||
| 		            type: "warning", | ||||
| 		            showCancelButton: true, | ||||
| 		            confirmButtonColor: "#DD6B55", | ||||
| 		            confirmButtonText: "{% trans 'Confirm' %}", | ||||
| 		            closeOnConfirm: false | ||||
| 		        }, function() { | ||||
| 		            var success = function() { | ||||
| 		                var msg = "{% trans 'Asset Deleted.' %}"; | ||||
| 		                swal("{% trans 'Asset Delete' %}", msg, "success"); | ||||
| 		                $('#idc_assets_table').DataTable().ajax.reload(); | ||||
| 		            }; | ||||
| 		            var fail = function() { | ||||
| 		                var msg = "{% trans 'Asset Deleting failed.' %}"; | ||||
| 		                swal("{% trans 'Asset Delete' %}", msg, "error"); | ||||
| 		            }; | ||||
| 		            var url_delete = "{% url 'api-assets:idc-update-assets' pk=idc.id %}"; | ||||
| 		            var body = { | ||||
| 				        assets: Object.assign([], assets) | ||||
| 				    }; | ||||
| 		            APIUpdateAttr({url: url_delete, body: JSON.stringify(body),  method: 'PUT', success: success, error: fail}); | ||||
| 		            jumpserver.checked = false; | ||||
|                 }); | ||||
| 		    } | ||||
| 		    function doUpdate() { | ||||
| 				$('#asset_bulk_update_modal').modal('show'); | ||||
| 		    } | ||||
| 		    switch (action) { | ||||
| 		        case 'delete': | ||||
| 		            doDelete(); | ||||
| 		            break; | ||||
| 		        case 'update': | ||||
| 		            doUpdate(); | ||||
| 		            break; | ||||
| 		        default: | ||||
| 		            break; | ||||
| 		    } | ||||
| 
 | ||||
| 	    } | ||||
|     }); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_asset_bulk_update', function () { | ||||
| 	var json_data = $("#fm_asset_bulk_update").serializeObject(); | ||||
| 	var body = {}; | ||||
|     body.enable_otp = (json_data.enable_otp === 'on')? true: false; | ||||
|     if (json_data.type != '') { | ||||
|         body.type = json_data.type; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.groups != undefined) { | ||||
|         body.groups = json_data.groups; | ||||
|     } | ||||
|     if (typeof body.groups === 'string') { | ||||
|         body.groups = [parseInt(body.groups)] | ||||
|     } else if(typeof body.groups === 'array') { | ||||
|         var new_groups = body.groups.map(Number); | ||||
|         body.groups = new_groups; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.users != undefined) { | ||||
|     	body.users = json_data.users; | ||||
|     } | ||||
|     if (typeof body.users === 'string') { | ||||
|     	body.users = [parseInt(body.users)] | ||||
|     } else if(typeof body.users === 'array') { | ||||
|     	var new_users = body.users.map(Number); | ||||
|     	body.users = new_users; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.tags != undefined) { | ||||
|     	body.tags = json_data.tags; | ||||
|     } | ||||
|     if (typeof body.tags == 'string') { | ||||
|     	body.tags = [parseInt(body.tags)]; | ||||
|     } else if (typeof body.tags === 'array') { | ||||
|     	var new_tags = body.tags.map(Number); | ||||
|     	body.tags = new_tags; | ||||
|     } | ||||
| 
 | ||||
|     var $data_table = $('#asset_list_table').DataTable(); | ||||
|     var post_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         var content = Object.assign({id: this.data().id}, body); | ||||
|         post_list.push(content); | ||||
|     }); | ||||
|     if (post_list === []) { | ||||
|         return false | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:asset-list' %}"; | ||||
|     var success = function() { | ||||
|         var msg = "{% trans 'The selected assets has been updated successfully.' %}"; | ||||
|         swal("{% trans 'Asset Updated' %}", msg, "success"); | ||||
|         $('#asset_list_table').DataTable().ajax.reload(); | ||||
|         jumpserver.checked = false; | ||||
|     }; | ||||
|     APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(post_list), success: success}); | ||||
|     $('#asset_bulk_update_modal').modal('hide'); | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -27,7 +27,7 @@ | |||
|                                 <a class="btn btn-outline btn-default" href="{% url 'assets:idc-update' pk=idc.id %}"><i class="fa fa-edit"></i>Update</a> | ||||
|                             </li> | ||||
|                             <li class="pull-right"> | ||||
|                                 <a class="btn btn-outline btn-danger" href="{% url 'assets:idc-delete' pk=idc.id %}"> | ||||
|                                 <a class="btn btn-outline btn-danger btn-delete-idc"> | ||||
|                                     <i class="fa fa-edit"></i>Delete | ||||
|                                 </a> | ||||
|                             </li> | ||||
|  | @ -53,9 +53,9 @@ | |||
|                                     </div> | ||||
|                                 </div> | ||||
|                                 <div class="ibox-content"> | ||||
|                                     <table class="table"> | ||||
|                                     <table class="table idc-details"> | ||||
|                                         <tbody> | ||||
|                                         <tr class="no-borders-tr"> | ||||
|                                         <tr class="no-borders-tr" data-name="{{ idc.name }}"> | ||||
|                                             <td>{% trans 'Name' %}:</td> | ||||
|                                             <td><b>{{ idc.name }}</b></td> | ||||
|                                         </tr> | ||||
|  | @ -113,26 +113,47 @@ | |||
| 
 | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
| {#        function switch_user_status(obj) {#} | ||||
| {#            var status = $(obj).prop('checked');#} | ||||
| {##} | ||||
| {#            $.ajax({#} | ||||
| {#                url: "{% url 'users:user-active-api' pk=user.id %}",#} | ||||
| {#                type: "PUT",#} | ||||
| {#                data: {#} | ||||
| {#                    'is_active': status#} | ||||
| {#                },#} | ||||
| {#                success: function (data, status) {#} | ||||
| {#                    console.log(data)#} | ||||
| {#                },#} | ||||
| {#                error: function () {#} | ||||
| {#                    console.log('error')#} | ||||
| {#                }#} | ||||
| {#            })#} | ||||
| {#        }#} | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
| <script> | ||||
| function idcDelete(name, url) { | ||||
|     function doDelete() { | ||||
|         var body = {}; | ||||
|         var success = function() { | ||||
|             swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success"); | ||||
| 	        window.location.href="{% url 'assets:idc-list' %}"; | ||||
|         }; | ||||
|         var fail = function() { | ||||
|             swal("Failed", "Delete"+"[ "+name+" ]"+"failed", "error"); | ||||
|         }; | ||||
|         APIUpdateAttr({ | ||||
|             url: url, | ||||
|             body: JSON.stringify(body), | ||||
|             method: 'DELETE', | ||||
|             success: success, | ||||
|             error: fail | ||||
|         }); | ||||
|     </script> | ||||
|     } | ||||
|     swal({ | ||||
|         title: 'Are you sure delete ?', | ||||
|         text: " [" + name + "] ", | ||||
|         type: "warning", | ||||
|         showCancelButton: true, | ||||
|         cancelButtonText: 'Cancel', | ||||
|         confirmButtonColor: "#DD6B55", | ||||
|         confirmButtonText: 'Confirm', | ||||
|         closeOnConfirm: false | ||||
|     }, function () { | ||||
|         doDelete() | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2(); | ||||
| }) | ||||
| .on('click', '.btn-delete-idc', function () { | ||||
| 	var name = $('.idc-details > tbody > tr').attr("data-name"); | ||||
| 	var id = {{ idc.id }}; | ||||
| 	var the_url = '{% url "api-assets:idc-detail" pk=99991937 %}'.replace(99991937, id); | ||||
| 	idcDelete(name, the_url); | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -1,5 +1,9 @@ | |||
| {% extends '_base_list.html' %} | ||||
| {% load i18n static %} | ||||
| {% 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 table_search %}{% endblock %} | ||||
| {% block table_container %} | ||||
| <div class="uc pull-left m-l-5 m-r-5"> | ||||
|  | @ -22,6 +26,18 @@ | |||
|     <tbody> | ||||
|     </tbody> | ||||
| </table> | ||||
| <div id="actions" class="hide"> | ||||
| 	<div class="input-group"> | ||||
| 		<select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
| 			<option value="delete">{% trans 'Delete selected' %}</option> | ||||
| 		</select> | ||||
| 		<div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
| 			<button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-warning"> | ||||
| 				{% trans 'Submit' %} | ||||
| 			</button> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| {% endblock %} | ||||
| {% block content_bottom_left %}{% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|  | @ -34,20 +50,10 @@ $(document).ready(function(){ | |||
|                 var detail_btn = '<a href="{% url "assets:idc-detail" pk=99991937 %}">' + cellData + '</a>'; | ||||
|                 $(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
|              }}, | ||||
| {#            {targets: 4, createdCell: function (td, cellData) {#} | ||||
| {#                var innerHtml = cellData.length > 8 ? cellData.substring(0, 8) + '...': cellData;#} | ||||
| {#                $(td).html('<a href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</a>');#} | ||||
| {#             }},#} | ||||
| {#            {targets: 6, createdCell: function (td, cellData) {#} | ||||
| {#                if (!cellData) {#} | ||||
| {#                    $(td).html('<i class="fa fa-times text-danger"></i>')#} | ||||
| {#                } else {#} | ||||
| {#                    $(td).html('<i class="fa fa-check text-navy"></i>')#} | ||||
| {#                }#} | ||||
| {#             }},#} | ||||
| 
 | ||||
|             {targets: 6, createdCell: function (td, cellData, rowData) { | ||||
|                 var update_btn = '<a href="{% url "assets:idc-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData); | ||||
|                 var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
|                 var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_idc_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
|                 $(td).html(update_btn + del_btn) | ||||
|              }}], | ||||
|         ajax_url: '{% url "api-assets:idc-list" %}', | ||||
|  | @ -56,6 +62,64 @@ $(document).ready(function(){ | |||
|         op_html: $('#actions').html() | ||||
|     }; | ||||
|     jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_idc_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $('#idc_list_table').DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:idc-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| {#	TODO: reload the tale #} | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $('#slct_bulk_update').val(); | ||||
| 	var $data_table = $('#idc_list_table').DataTable(); | ||||
|     var id_list = []; | ||||
|     var plain_id_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (id_list === []) { | ||||
|         return false; | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:idc-list' %}"; | ||||
|     function doDelete() { | ||||
|         swal({ | ||||
|             title: "{% trans 'Are you sure?' %}", | ||||
|             text: "{% trans 'This will delete the selected idc !!!' %}", | ||||
|             type: "warning", | ||||
|             showCancelButton: true, | ||||
|             confirmButtonColor: "#DD6B55", | ||||
|             confirmButtonText: "{% trans 'Confirm' %}", | ||||
|             closeOnConfirm: false | ||||
|         }, function() { | ||||
|             var success = function() { | ||||
|                 var msg = "{% trans 'IDC Deleted.' %}"; | ||||
|                 swal("{% trans 'IDC Delete' %}", msg, "success"); | ||||
|                 $('#idc_list_table').DataTable().ajax.reload(); | ||||
|             }; | ||||
|             var fail = function() { | ||||
|                 var msg = "{% trans 'IDC Deleting failed.' %}"; | ||||
|                 swal("{% trans 'IDC Delete' %}", msg, "error"); | ||||
|             }; | ||||
|             var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); | ||||
|             APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail}); | ||||
|             $data_table.ajax.reload(); | ||||
|             jumpserver.checked = false; | ||||
|         }); | ||||
|     } | ||||
| 	switch (action) { | ||||
| 		case 'delete': | ||||
| 			doDelete(); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  |  | |||
|  | @ -43,35 +43,35 @@ | |||
|                                     </div> | ||||
|                                 </div> | ||||
|                                 <div class="ibox-content"> | ||||
|                                     <table class="table table-hover"> | ||||
|                                     <table class="table table-hover" id="system_user_list"> | ||||
|                                         <thead> | ||||
|                                             <tr> | ||||
|                                                 <th>{% trans 'Hostname' %}</th> | ||||
|                                                 <th>{% trans 'IP' %}</th> | ||||
|                                                 <th>{% trans 'Port' %}</th> | ||||
|                                                 <th>{% trans 'Reachable' %}</th> | ||||
|                                                 <th></th> | ||||
|                                                 <th>{% trans 'Action' %}</th> | ||||
|                                             </tr> | ||||
|                                         </thead> | ||||
|                                         <tbody> | ||||
|                                             {% for asset in page_obj %} | ||||
|                                             <tr> | ||||
|                                                 <td>{{ asset.hostname }}</td> | ||||
|                                                 <td>{{ asset.ip }}</td> | ||||
|                                                 <td>{{ asset.port }}</td> | ||||
|                                                 <td> | ||||
|                                                     <i class="fa fa-check text-navy"></i> | ||||
|                                                 </td> | ||||
|                                                 <td> | ||||
|                                                     <button class="btn btn-danger pull-right btn-xs {% if asset.is_inherit_from_asset_groups %} disabled {% endif %}" type="button"><i class="fa fa-minus"></i></button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             {% endfor %} | ||||
| {#                                            {% for asset in page_obj %}#} | ||||
| {#                                            <tr>#} | ||||
| {#                                                <td>{{ asset.hostname }}</td>#} | ||||
| {#                                                <td>{{ asset.ip }}</td>#} | ||||
| {#                                                <td>{{ asset.port }}</td>#} | ||||
| {#                                                <td>#} | ||||
| {#                                                    <i class="fa fa-check text-navy"></i>#} | ||||
| {#                                                </td>#} | ||||
| {#                                                <td>#} | ||||
| {#                                                    <button class="btn btn-danger pull-right btn-xs {% if asset.is_inherit_from_asset_groups %} disabled {% endif %}" type="button"><i class="fa fa-minus"></i></button>#} | ||||
| {#                                                </td>#} | ||||
| {#                                            </tr>#} | ||||
| {#                                            {% endfor %}#} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                     <div class="row"> | ||||
|                                         {% include '_pagination.html' %} | ||||
|                                     </div> | ||||
| {#                                    <div class="row">#} | ||||
| {#                                        {% include '_pagination.html' %}#} | ||||
| {#                                    </div>#} | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|  | @ -95,7 +95,7 @@ | |||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm">{% trans 'Attach' %}</button> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm btn-add-asset2system-user">{% trans 'Attach Asset' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|  | @ -123,16 +123,16 @@ | |||
|                                             </tr> | ||||
|                                             <tr> | ||||
|                                                 <td colspan="2" class="no-borders"> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm" id="btn_add_user_group">{% trans 'Attach' %}</button> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm" id="btn_add_user_group">{% trans 'Attach AssetGroup' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
| 
 | ||||
|                                         {% for asset_group in asset_groups %} | ||||
|                                         <tr> | ||||
|                                           <td ><b data-gid={{ asset_group.id }}>{{ asset_group.name }}</b></td> | ||||
|                                           <td ><b class="bdg_asset_groups" data-gid={{ asset_group.id }}>{{ asset_group.name }}</b></td> | ||||
|                                           <td> | ||||
|                                               <button class="btn btn-danger pull-right btn-xs" type="button"><i class="fa fa-minus"></i></button> | ||||
|                                               <button class="btn btn-danger pull-right btn-xs btn-leave-system_user" type="button"><i class="fa fa-minus"></i></button> | ||||
|                                           </td> | ||||
|                                         </tr> | ||||
|                                         {% endfor %} | ||||
|  | @ -150,26 +150,224 @@ | |||
| 
 | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
| {#        function switch_user_status(obj) {#} | ||||
| {#            var status = $(obj).prop('checked');#} | ||||
| {##} | ||||
| {#            $.ajax({#} | ||||
| {#                url: "{% url 'users:user-active-api' pk=user.id %}",#} | ||||
| {#                type: "PUT",#} | ||||
| {#                data: {#} | ||||
| {#                    'is_active': status#} | ||||
| {#                },#} | ||||
| {#                success: function (data, status) {#} | ||||
| {#                    console.log(data)#} | ||||
| {#                },#} | ||||
| {#                error: function () {#} | ||||
| {#                    console.log('error')#} | ||||
| {#                }#} | ||||
| {#            })#} | ||||
| {#        }#} | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
| <script> | ||||
| jumpserver.assets_selected = {}; | ||||
| jumpserver.asset_groups_selected = {}; | ||||
| Array.prototype.remove = function(val) { | ||||
| 	var index = this.indexOf(val); | ||||
| 		if (index > -1) { | ||||
| 		this.splice(index, 1); | ||||
| 	} | ||||
| }; | ||||
| Array.prototype.unique = function(){ | ||||
| 	var res = []; | ||||
| 	var json = {}; | ||||
|  	for(var i = 0; i < this.length; i++){ | ||||
|   		if(!json[this[i]]){ | ||||
|    			res.push(this[i]); | ||||
|    			json[this[i]] = 1; | ||||
|   		} | ||||
|  	} | ||||
|  	return res; | ||||
| }; | ||||
| function objectDelete(obj, name, url, data) { | ||||
|     function doDelete() { | ||||
|         var body = data; | ||||
|         var success = function() { | ||||
|             swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success"); | ||||
|             $(obj).parent().parent().remove(); | ||||
|         }; | ||||
|         var fail = function() { | ||||
|             swal("Failed", "Delete"+"[ "+name+" ]"+"failed", "error"); | ||||
|         }; | ||||
|         APIUpdateAttr({ | ||||
|             url: url, | ||||
|             body: JSON.stringify(body), | ||||
|             method: 'PATCH', | ||||
|             success: success, | ||||
|             error: fail | ||||
|         }); | ||||
|     </script> | ||||
|     } | ||||
|     swal({ | ||||
|         title: 'Are you sure delete ?', | ||||
|         text: " [" + name + "] ", | ||||
|         type: "warning", | ||||
|         showCancelButton: true, | ||||
|         cancelButtonText: 'Cancel', | ||||
|         confirmButtonColor: "#DD6B55", | ||||
|         confirmButtonText: 'Confirm', | ||||
|         closeOnConfirm: false | ||||
|     }, function () { | ||||
|         doDelete() | ||||
|     }); | ||||
| } | ||||
| function updateSystemUserAssetGroup(asset_groups) { | ||||
| 	var the_url = "{% url 'api-assets:systemuser-update-assetgroups' pk=system_user.id %}"; | ||||
|     var body = { | ||||
|         asset_groups: Object.assign([], asset_groups) | ||||
|     }; | ||||
|     var success = function(data) { | ||||
|         $('.select2-selection__rendered').empty(); | ||||
|         $('#groups_selected').val(''); | ||||
|         $.map(jumpserver.asset_groups_selected, function(asset_groups, index) { | ||||
|             $('#opt_' + index).remove(); | ||||
|             $('.system-user-table tbody').append( | ||||
|                 '<tr>' + | ||||
|                 '<td><b class="bdg_asset_groups" data-sid="' + index + '">' + asset_groups + '</b></td>' + | ||||
|                 '<td><button class="btn btn-danger btn-xs pull-right btn-leave-system_user" type="button"><i class="fa fa-minus"></i></button></td>' + | ||||
|                 '</tr>' | ||||
|             ) | ||||
|         }); | ||||
|         jumpserver.assets_selected = {}; | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2() | ||||
| 	.on("select2:select", function (evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		jumpserver.assets_selected[data.id] = data.text; | ||||
| 		jumpserver.asset_groups_selected[data.id] = data.text; | ||||
| 	}) | ||||
| 	.on('select2:unselect', function(evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		delete jumpserver.assets_selected[data.id]; | ||||
| 		delete jumpserver.asset_groups_selected[data.id]; | ||||
| 	}); | ||||
| 	var options = { | ||||
| 		ele: $('#system_user_list'), | ||||
| 		buttons: [], | ||||
| 		order: [], | ||||
| 		columnDefs: [ | ||||
| 			{targets: 0, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}" data-aid="'+rowData.id+'">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 3, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-times text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-check text-navy"></i>') | ||||
| 				} | ||||
| 			}}, | ||||
| 			{targets: 4, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', rowData.id); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-aid="99991937">{% trans "Delete" %}</a>'.replace('99991937', rowData.id); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 			], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}?system_user_id={{ system_user.id }}', | ||||
| 		columns: [{data: "hostname" }, {data: "ip" }, {data: "port" }, {data: function () { return ""; } }, {data: "id"}], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-add-asset2system-user', function () { | ||||
| 	if (Object.keys(jumpserver.assets_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	var $data_table = $("#system_user_list").DataTable(); | ||||
| 	var assets = []; | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:asset-list" %}?system_user_id={{ system_user.id }}', | ||||
| 		method: 'GET', | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for(var i in result){ | ||||
| 				if (!isNaN(parseInt(result[i]['id']))) { | ||||
| 					assets.push(parseInt(result[i]['id'])) | ||||
| 				} | ||||
| 			} | ||||
| 			$.map(jumpserver.assets_selected, function(value, index) { | ||||
| 				assets.push(parseInt(index)); | ||||
| 			}); | ||||
| 			assets.unique(); | ||||
| 			var the_url = "{% url 'api-assets:systemuser-update-assets' pk=system_user.id %}"; | ||||
| 			var body = {"assets": assets}; | ||||
| 			APIUpdateAttr({ | ||||
| 				url: the_url, | ||||
| 	            body: JSON.stringify(body), | ||||
| 	            method: 'PATCH' | ||||
| 			}); | ||||
| 			$data_table.ajax.reload(); | ||||
| 		} | ||||
| 	}); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_asset_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var the_url = "{% url 'api-assets:systemuser-update-assets' pk=system_user.id %}"; | ||||
| 	var name = $(this).closest("tr").find(":nth-child(1) > a").html(); | ||||
| 	var $data_table = $("#system_user_list").DataTable(); | ||||
| 	var assets = []; | ||||
| 	$('#system_user_list > tbody > tr').map(function () { | ||||
| 		assets.push(parseInt($(this).closest("tr").find(":nth-child(1) > a").attr("data-aid"))) | ||||
| 	}); | ||||
| 	var delete_asset_id = $(this).data('aid'); | ||||
| 	assets.remove(delete_asset_id); | ||||
| 	assets.unique(); | ||||
| 	var data = {"assets": assets}; | ||||
| 	objectDelete($this, name, the_url, data); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 	 | ||||
| .on('click', '#btn_add_user_group', function () { | ||||
| 	jumpserver.assets_selected = {}; | ||||
| 	if (Object.keys(jumpserver.asset_groups_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	asset_groups = []; | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:systemuser-update-assetgroups" pk=system_user.id %}', | ||||
| 		method: 'GET', | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for (var i in result['asset_groups']) { | ||||
| 				if (!isNaN(result['asset_groups'][i])) { | ||||
| 					asset_groups.push(parseInt(result['asset_groups'][i])); | ||||
| 				} | ||||
| 			} | ||||
| 			$.map(jumpserver.asset_groups_selected, function(value, index) { | ||||
| 				asset_groups.push(parseInt(index)); | ||||
| 			}); | ||||
| 			asset_groups.unique(); | ||||
| 			console.log(asset_groups); | ||||
| 			var the_url = '{% url "api-assets:systemuser-update-assetgroups" pk=system_user.id %}'; | ||||
| 			var body = {"asset_groups": asset_groups}; | ||||
| 			APIUpdateAttr({ | ||||
| 				url: the_url, | ||||
| 	            body: JSON.stringify(body), | ||||
| 	            method: 'PATCH' | ||||
| 			}); | ||||
| {#			TODO: reload the table #} | ||||
| {#			window.location.href="{% url 'assets:system-user-asset' pk=system_user.id %}"#} | ||||
| 		} | ||||
| 	}); | ||||
| }) | ||||
| 	 | ||||
| .on('click', '.btn-leave-system_user', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $tr = $this.closest('tr'); | ||||
| 	var $badge = $tr.find('.bdg_asset_groups'); | ||||
| 	var sid = $badge.data('gid'); | ||||
| 	var name = $badge.html() || $badge.text(); | ||||
| 	$('system-user-table').append( | ||||
| 		'<option value="' + sid + '" id="opt_' + sid + '">' + name + '</option>' | ||||
| 	); | ||||
| 	$tr.remove(); | ||||
| 	var asset_groups = $('.bdg_asset_groups').map(function () { | ||||
| 		return $(this).data('gid'); | ||||
| 	}).get(); | ||||
| 	updateSystemUserAssetGroup(asset_groups); | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -26,10 +26,23 @@ | |||
|     <tbody> | ||||
|     </tbody> | ||||
| </table> | ||||
| <div id="actions" class="hide"> | ||||
| 	<div class="input-group"> | ||||
| 		<select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
| 			<option value="delete">{% trans 'Delete selected' %}</option> | ||||
| 			<option value="update">{% trans 'Update selected' %}</option> | ||||
| 		</select> | ||||
| 		<div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
| 			<button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-warning"> | ||||
| 				{% trans 'Submit' %} | ||||
| 			</button> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
| <script> | ||||
|     $(document).ready(function(){ | ||||
| $(document).ready(function(){ | ||||
| 	var options = { | ||||
| 		ele: $('#system_user_list_table'), | ||||
| 		columnDefs: [ | ||||
|  | @ -50,9 +63,73 @@ | |||
| 		ajax_url: '{% url "api-assets:system-user-list" %}', | ||||
| 		columns: [{data: "id" }, {data: "name" }, {data: "username" }, {data: "assets_amount" }, {data: function () { return "3"}}, | ||||
| 			{data: "comment" }, {data: "id" }], | ||||
| 		op_html: $('#actions').html() | ||||
|         }; | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_admin_user_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $('#idc_list_table').DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:system-user-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $('#slct_bulk_update').val(); | ||||
| 	var $data_table = $('#system_user_list_table').DataTable(); | ||||
|     var id_list = []; | ||||
|     var plain_id_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (id_list === []) { | ||||
|         return false; | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:system-user-list' %}"; | ||||
|     function doDelete() { | ||||
|         swal({ | ||||
|             title: "{% trans 'Are you sure?' %}", | ||||
|             text: "{% trans 'This will delete the selected System Users !!!' %}", | ||||
|             type: "warning", | ||||
|             showCancelButton: true, | ||||
|             confirmButtonColor: "#DD6B55", | ||||
|             confirmButtonText: "{% trans 'Confirm' %}", | ||||
|             closeOnConfirm: false | ||||
|         }, function() { | ||||
|             var success = function() { | ||||
|                 var msg = "{% trans 'System Users Deleted.' %}"; | ||||
|                 swal("{% trans 'System Users Delete' %}", msg, "success"); | ||||
|                 $('#system_user_list_table').DataTable().ajax.reload(); | ||||
|             }; | ||||
|             var fail = function() { | ||||
|                 var msg = "{% trans 'System Users Deleting failed.' %}"; | ||||
|                 swal("{% trans 'System Users Delete' %}", msg, "error"); | ||||
|             }; | ||||
|             var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); | ||||
|             APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail}); | ||||
|             $data_table.ajax.reload(); | ||||
|             jumpserver.checked = false; | ||||
|         }); | ||||
|     } | ||||
|     function doUpdate() { | ||||
| {#		TODO: bulk update the System Users #} | ||||
|     } | ||||
|     switch (action) { | ||||
| 	    case 'delete': | ||||
| 	    	doDelete(); | ||||
| 	    	break; | ||||
| 	    case 'update': | ||||
| 	    	doUpdate(); | ||||
| 	    	break; | ||||
| 	    default: | ||||
| 	    	break; | ||||
|     } | ||||
| }) | ||||
| </script> | ||||
| {% endblock %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,16 +2,18 @@ | |||
| from django.conf.urls import url | ||||
| from .. import api | ||||
| from rest_framework import routers | ||||
| from rest_framework_bulk.routes import BulkRouter | ||||
| 
 | ||||
| app_name = 'assets' | ||||
| 
 | ||||
| 
 | ||||
| router = routers.DefaultRouter() | ||||
| router = BulkRouter() | ||||
| router.register(r'v1/asset-groups', api.AssetGroupViewSet, 'asset-group') | ||||
| router.register(r'v1/assets', api.AssetViewSet, 'asset') | ||||
| router.register(r'v1/idc', api.IDCViewSet, 'idc') | ||||
| router.register(r'v1/admin-user', api.AdminUserViewSet, 'admin-user') | ||||
| router.register(r'v1/system-user', api.SystemUserViewSet, 'system-user') | ||||
| router.register(r'v1/tags', api.TagViewSet, 'asset-tag') | ||||
| 
 | ||||
| urlpatterns = [ | ||||
|     url(r'^v1/assets_bulk/$', api.AssetListUpdateApi.as_view(), name='asset-bulk-update'), | ||||
|  | @ -20,8 +22,31 @@ urlpatterns = [ | |||
| 
 | ||||
|     url(r'^v1/assets/(?P<pk>\d+)/groups/$', | ||||
|         api.AssetUpdateGroupApi.as_view(), name='asset-update-group'), | ||||
| 
 | ||||
|     url(r'^v1/assets/(?P<pk>\d+)/system-users/$', | ||||
|         api.SystemUserUpdateApi.as_view(), name='asset-update-systemusers'), | ||||
| 
 | ||||
| 	## update the system users, which add and delete the asset to the system user | ||||
| 	url(r'^v1/system_user/(?P<pk>\d+)/assets/$', | ||||
| 	    api.SystemUserUpdateAssetsApi.as_view(), name='systemuser-update-assets'), | ||||
| 
 | ||||
|     url(r'^v1/system_user/(?P<pk>\d+)/groups/$', | ||||
|         api.SystemUserUpdateAssetGroupApi.as_view(), name='systemuser-update-assetgroups'), | ||||
| 
 | ||||
| 	## update the asset group, which add or delete the asset to the group | ||||
|     url(r'^v1/groups/(?P<pk>\d+)/assets/$', | ||||
|         api.AssetGroupUpdateApi.as_view(), name='asset-groups-update'), | ||||
| 	## update the asset group, and add or delete the system_user to the group | ||||
|     url(r'^v1/groups/(?P<pk>\d+)/system-users/$', | ||||
|         api.AssetGroupUpdateSystemUserApi.as_view(), name='asset-groups-update-systemusers'), | ||||
|     ## update the IDC, and add or delete the assets to the IDC | ||||
|     url(r'^v1/idc/(?P<pk>\d+)/assets/$', | ||||
|         api.IDCupdateAssetsApi.as_view(), name='idc-update-assets'), | ||||
| 
 | ||||
|     url(r'v1/tag/(?P<pk>\d+)/assets/$', | ||||
|         api.TagUpdateAssetsApi.as_view(), name='tag-update-assets'), | ||||
| 
 | ||||
| 
 | ||||
| ] | ||||
| 
 | ||||
| urlpatterns += router.urls | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ 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 django.http import HttpResponse, JsonResponse | ||||
| from django.http import HttpResponse, JsonResponse, HttpResponseRedirect | ||||
| from django.views.decorators.csrf import csrf_protect, csrf_exempt | ||||
| from django.utils.decorators import method_decorator | ||||
| from django.core.cache import cache | ||||
|  | @ -37,8 +37,10 @@ class AssetListView(AdminUserRequiredMixin, TemplateView): | |||
| 		context = { | ||||
| 			'app': 'Assets', | ||||
| 			'action': 'asset list', | ||||
|             'tag_list': [(i.id, i.name, i.asset_set.all().count())for i in Tag.objects.all().order_by('name')] | ||||
| 
 | ||||
| 			'groups': AssetGroup.objects.all(), | ||||
| 			'system_users': SystemUser.objects.all(), | ||||
| 			'tag_list': [(i.id, i.name, i.assets.all().count())for i in Tag.objects.all().order_by('name')], | ||||
| 			'tags': Tag.objects.all().order_by('name') | ||||
| 		} | ||||
| 		kwargs.update(context) | ||||
| 		return super(AssetListView, self).get_context_data(**kwargs) | ||||
|  | @ -261,6 +263,8 @@ class AssetGroupListView(AdminUserRequiredMixin, TemplateView): | |||
| 		context = { | ||||
| 			'app': _('Assets'), | ||||
| 			'action': _('Asset group list'), | ||||
| 			'assets': Asset.objects.all(), | ||||
| 			'system_users': SystemUser.objects.all(), | ||||
| 			'keyword': self.request.GET.get('keyword', '') | ||||
| 		} | ||||
| 		kwargs.update(context) | ||||
|  | @ -280,6 +284,7 @@ class AssetGroupDetailView(AdminUserRequiredMixin, DetailView): | |||
| 			'app': _('Assets'), | ||||
| 			'action': _('Asset group detail'), | ||||
| 			'assets_remain': assets_remain, | ||||
| 			'assets': [asset for asset in Asset.objects.all() if asset not in assets_remain], | ||||
| 			'system_users': system_users, | ||||
| 			'system_users_remain': system_users_remain, | ||||
| 		} | ||||
|  | @ -383,6 +388,22 @@ class IDCAssetsView(AdminUserRequiredMixin, DetailView): | |||
| 	template_name = 'assets/idc_assets.html' | ||||
| 	context_object_name = 'idc' | ||||
| 
 | ||||
| 	def get_context_data(self, **kwargs): | ||||
| 		assets_remain = Asset.objects.exclude(id__in=self.object.assets.all()) | ||||
| 
 | ||||
| 		context = { | ||||
| 			'app': _('Assets'), | ||||
| 			'action': _('Asset detail'), | ||||
| 			'groups': AssetGroup.objects.all(), | ||||
| 			'system_users': SystemUser.objects.all(), | ||||
| 			'tags': Tag.objects.all(), | ||||
| 			'assets_remain': assets_remain, | ||||
| 			'assets': [asset for asset in Asset.objects.all() if asset not in assets_remain], | ||||
| 		} | ||||
| 		kwargs.update(context) | ||||
| 		return super(IDCAssetsView, self).get_context_data(**kwargs) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| class IDCDeleteView(AdminUserRequiredMixin, DeleteView): | ||||
| 	model = IDC | ||||
|  | @ -477,10 +498,19 @@ class AdminUserDetailView(AdminUserRequiredMixin, SingleObjectMixin, ListView): | |||
| 	def get_queryset(self): | ||||
| 		return self.object.assets.all() | ||||
| 
 | ||||
| 	# def get_asset_groups(self): | ||||
| 	# 	return self.object.asset_groups.all() | ||||
| 
 | ||||
| 	def get_context_data(self, **kwargs): | ||||
| 		asset_groups = AssetGroup.objects.all() | ||||
| 		assets = self.get_queryset() | ||||
| 		context = { | ||||
| 			'app': 'assets', | ||||
|             'action': 'Admin user detail' | ||||
| 			'action': 'Admin user detail', | ||||
| 			'assets_remain': [asset for asset in Asset.objects.all() if asset not in assets], | ||||
| 		    'asset_groups': asset_groups, | ||||
| 		    # 'asset_groups_remain': [asset_group for asset_group in AssetGroup.objects.all() | ||||
| 		    #                         if asset_group not in asset_groups] | ||||
| 		} | ||||
| 		kwargs.update(context) | ||||
| 		return super(AdminUserDetailView, self).get_context_data(**kwargs) | ||||
|  | @ -630,7 +660,7 @@ class TagsListView(AdminUserRequiredMixin, ListView): | |||
| 		return super(TagsListView, self).get_context_data(**kwargs) | ||||
| 
 | ||||
| 
 | ||||
| class AssetTagCreateView(AdminUserRequiredMixin, CreateView): | ||||
| class AssetTagCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, CreateView): | ||||
| 	model = Tag | ||||
| 	form_class = forms.AssetTagForm | ||||
| 	template_name = 'assets/asset_tag_create.html' | ||||
|  | @ -653,7 +683,7 @@ class AssetTagCreateView(AdminUserRequiredMixin, CreateView): | |||
| 		assets_id_list = self.request.POST.getlist('assets', []) | ||||
| 		assets = [get_object_or_404(Asset, id=int(asset_id)) for asset_id in assets_id_list] | ||||
| 		asset_tag.created_by = self.request.user.username or 'Admin' | ||||
|         asset_tag.asset_set.add(*tuple(assets)) | ||||
| 		asset_tag.assets.add(*tuple(assets)) | ||||
| 		asset_tag.save() | ||||
| 		return super(AssetTagCreateView, self).form_valid(form) | ||||
| 
 | ||||
|  | @ -662,18 +692,22 @@ class AssetTagDetailView(SingleObjectMixin, AdminUserRequiredMixin, ListView): | |||
| 	template_name = 'assets/asset_tag_detail.html' | ||||
| 	paginate_by = settings.CONFIG.DISPLAY_PER_PAGE | ||||
| 
 | ||||
| 
 | ||||
| 	def get(self, request, *args, **kwargs): | ||||
| 		self.object = self.get_object(queryset=Tag.objects.all()) | ||||
| 		return super(AssetTagDetailView, self).get(request, *args, **kwargs) | ||||
| 
 | ||||
| 	def get_queryset(self): | ||||
|         return self.object.asset_set.all() | ||||
| 		return self.object.assets.all() | ||||
| 
 | ||||
| 	def get_context_data(self, **kwargs): | ||||
| 		assets_remain = Asset.objects.exclude(id__in=self.object.assets.all()) | ||||
| 		context = { | ||||
| 			'app': _('Tag'), | ||||
| 			'action': _('Asset Tags detail'), | ||||
| 			'asset_tag': self.object, | ||||
| 			'assets_remain': assets_remain, | ||||
| 			'assets': [asset for asset in Asset.objects.all() if asset not in assets_remain] | ||||
| 		} | ||||
| 		kwargs.update(context) | ||||
| 		return super(AssetTagDetailView, self).get_context_data(**kwargs) | ||||
|  | @ -690,7 +724,7 @@ class AssetTagUpdateView(AdminUserRequiredMixin, UpdateView): | |||
| 		return super(AssetTagUpdateView, self).get(request, *args, **kwargs) | ||||
| 
 | ||||
| 	def get_context_data(self, **kwargs): | ||||
|         assets_all = self.object.asset_set.all() | ||||
| 		assets_all = self.object.assets.all() | ||||
| 		context = { | ||||
| 			'app': _('Tag'), | ||||
| 			'action': _('Asset Tags detail'), | ||||
|  | @ -713,9 +747,9 @@ class AssetExportView(View): | |||
| 	@staticmethod | ||||
| 	def get_asset_attr(asset, attr): | ||||
| 		if attr in ['admin_user', 'idc']: | ||||
|             return getattr(asset, attr).name | ||||
|         elif attr in ['status', 'type', 'env']: | ||||
|             return getattr(asset, 'get_{}_display'.format(attr))() | ||||
| 			return getattr(asset, attr) | ||||
| 		# elif attr in ['status', 'type', 'env']: | ||||
| 		# 	return getattr(asset, 'get_{}_display'.format(attr)) | ||||
| 		else: | ||||
| 			return getattr(asset, attr) | ||||
| 
 | ||||
|  | @ -735,8 +769,10 @@ class AssetExportView(View): | |||
| 		ws.append(header) | ||||
| 
 | ||||
| 		for asset in assets: | ||||
| 			print [self.get_asset_attr(asset, attr) for attr in header] | ||||
| 			ws.append([self.get_asset_attr(asset, attr) for attr in header]) | ||||
| 
 | ||||
| 
 | ||||
| 		filename = 'assets-{}.xlsx'.format(timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S')) | ||||
| 		response = HttpResponse(save_virtual_workbook(wb), content_type='application/vnd.ms-excel') | ||||
| 		response['Content-Disposition'] = 'attachment; filename="%s"' % filename | ||||
|  | @ -745,13 +781,13 @@ class AssetExportView(View): | |||
| 	def post(self, request, *args, **kwargs): | ||||
| 		try: | ||||
| 			assets_id = json.loads(request.body).get('assets_id', []) | ||||
|             print(assets_id) | ||||
| 		except ValueError: | ||||
| 			return HttpResponse('Json object not valid', status=400) | ||||
| 		spm = uuid.uuid4().get_hex() | ||||
| 		cache.set(spm, assets_id, 300) | ||||
| 		url = reverse('assets:asset-export') + '?spm=%s' % spm | ||||
|         return JsonResponse({'redirect': url}) | ||||
| 		print url | ||||
| 		return HttpResponse({'redirect': url}) | ||||
| 
 | ||||
| 
 | ||||
| class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView): | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 右书僮
						右书僮