[Bugfix] 修改翻译

pull/417/head
ibuler 2017-04-07 16:59:09 +08:00
parent 92ebe85a3f
commit c11374ae39
37 changed files with 628 additions and 1157 deletions

View File

@ -44,11 +44,11 @@
<td><b>{{ terminal.name }}</b></td> <td><b>{{ terminal.name }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Remote addr' %}:</td> <td>{% trans 'Remote address' %}:</td>
<td><b>{{ terminal.remote_addr }}</b></td> <td><b>{{ terminal.remote_addr }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Terminal url' %}:</td> <td>{% trans 'URL to login' %}:</td>
<td><b>{{ terminal.url }}</b></td> <td><b>{{ terminal.url }}</b></td>
</tr> </tr>
<tr> <tr>

View File

@ -97,7 +97,7 @@ class TerminalConnectView(LoginRequiredMixin, DetailView):
if self.object.type == 'Web': if self.object.type == 'Web':
context = { context = {
'title': _('Redirect to web terminal'), 'title': _('Redirect to web terminal'),
'messages': _('Redirect to web terminal: {}'.format(self.object.url)), 'messages': _('Redirect to web terminal') + self.object.url,
'auto_redirect': True, 'auto_redirect': True,
'interval': 3, 'interval': 3,
'redirect_url': self.object.url 'redirect_url': self.object.url

View File

@ -80,13 +80,8 @@ class AssetGroupForm(forms.ModelForm):
class Meta: class Meta:
model = AssetGroup model = AssetGroup
fields = [ fields = [
"name", "comment", "system_users", "name", "comment",
] ]
widgets = {
'name': forms.TextInput(attrs={}),
'system_users': forms.SelectMultiple(attrs={'class': 'select2-system-user', 'data-placeholder': _('Select asset system user')}),
}
help_texts = { help_texts = {
'name': '* required', 'name': '* required',
} }
@ -94,12 +89,13 @@ class AssetGroupForm(forms.ModelForm):
class IDCForm(forms.ModelForm): class IDCForm(forms.ModelForm):
# See AdminUserForm comment same it # See AdminUserForm comment same it
assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), assets = forms.ModelMultipleChoiceField(
label=_('Asset'), queryset=Asset.objects.all(),
required=False, label=_('Asset'),
widget=forms.SelectMultiple( required=False,
attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) widget=forms.SelectMultiple(
) attrs={'class': 'select2', 'data-placeholder': _('Select assets')})
)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if kwargs.get('instance'): if kwargs.get('instance'):
@ -249,7 +245,7 @@ class SystemUserForm(forms.ModelForm):
key_string = self.cleaned_data['private_key_file'].read() key_string = self.cleaned_data['private_key_file'].read()
self.cleaned_data['private_key_file'].seek(0) self.cleaned_data['private_key_file'].seek(0)
if not validate_ssh_private_key(key_string): if not validate_ssh_private_key(key_string):
raise forms.ValidationError(_('Private key invalid')) raise forms.ValidationError(_('Invalid private key'))
return self.cleaned_data['private_key_file'] return self.cleaned_data['private_key_file']
def clean_password(self): def clean_password(self):

View File

@ -76,12 +76,12 @@ class Asset(models.Model):
platform = models.CharField(max_length=128, null=True, blank=True, verbose_name='Platform') platform = models.CharField(max_length=128, null=True, blank=True, verbose_name='Platform')
os = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('OS')) os = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('OS'))
os_version = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('OS Version')) os_version = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('OS version'))
os_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=_('OS Arch')) os_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=_('OS arch'))
hostname_raw = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Hostname raw')) hostname_raw = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Hostname raw'))
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date added')) date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date created'))
comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment')) comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment'))
def __unicode__(self): def __unicode__(self):

View File

@ -18,7 +18,7 @@ class AssetGroup(models.Model):
name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) name = models.CharField(max_length=64, unique=True, verbose_name=_('Name'))
system_users = models.ManyToManyField(SystemUser, related_name='asset_groups', blank=True) system_users = models.ManyToManyField(SystemUser, related_name='asset_groups', blank=True)
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by')) created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date added')) date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date created'))
comment = models.TextField(blank=True, verbose_name=_('Comment')) comment = models.TextField(blank=True, verbose_name=_('Comment'))
def __unicode__(self): def __unicode__(self):

View File

@ -27,7 +27,7 @@ class IDC(models.Model):
intranet = models.TextField(blank=True, verbose_name=_('Intranet')) intranet = models.TextField(blank=True, verbose_name=_('Intranet'))
extranet = models.TextField(blank=True, verbose_name=_('Extranet')) extranet = models.TextField(blank=True, verbose_name=_('Extranet'))
date_created = models.DateTimeField( date_created = models.DateTimeField(
auto_now_add=True, null=True, verbose_name=_('Date added')) auto_now_add=True, null=True, verbose_name=_('Date created'))
operator = models.CharField( operator = models.CharField(
max_length=32, blank=True, verbose_name=_('Operator')) max_length=32, blank=True, verbose_name=_('Operator'))
created_by = models.CharField( created_by = models.CharField(

View File

@ -17,7 +17,7 @@
</div> </div>
<form method="post" class="form-horizontal" action="" id="fm_asset_bulk_update"> <form method="post" class="form-horizontal" action="" id="fm_asset_bulk_update">
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2 col-lg-2 " for="id_type">{% trans "System Type" %}</label> <label class="control-label col-sm-2 col-lg-2 " for="id_type">{% trans "Asset type" %}</label>
<div class=" col-sm-9 col-lg-9 "> <div class=" col-sm-9 col-lg-9 ">
<select class=" select2 form-control" id="id_type" name="type"> <select class=" select2 form-control" id="id_type" name="type">
<option value="">---------</option> <option value="">---------</option>
@ -34,7 +34,7 @@
<div class="form-group"> <div class="form-group">
<label for="groups" class="col-sm-2 control-label">{% trans 'Asset Groups' %}</label> <label for="groups" class="col-sm-2 control-label">{% trans 'Asset Groups' %}</label>
<div class="col-sm-9" id="select2-container"> <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> <select name="groups" id="select2_groups" data-placeholder="{% trans 'Select groups' %}" class="select2 form-control m-b" multiple>
{% for group in groups %} {% for group in groups %}
<option value="{{ group.id }}">{{ group.name }}</option> <option value="{{ group.id }}">{{ group.name }}</option>
{% endfor %} {% endfor %}
@ -43,9 +43,9 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="users" class="col-sm-2 control-label">{% trans 'System Users' %}</label> <label for="users" class="col-sm-2 control-label">{% trans 'System users' %}</label>
<div class="col-sm-9" id="select2-container"> <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> <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 %} {% for system_user in system_users %}
<option value="{{ system_user.id }}">{{ system_user.name }}</option> <option value="{{ system_user.id }}">{{ system_user.name }}</option>
{% endfor %} {% endfor %}

View File

@ -19,7 +19,7 @@
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="system_users" class="col-sm-2 control-label">{% trans 'System Users' %}</label> <label for="system_users" class="col-sm-2 control-label">{% trans 'System users' %}</label>
<div class="col-sm-9" id="select2-container"> <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> <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 %} {% for system_user in system_users %}

View File

@ -85,11 +85,11 @@
<td><b>{{ asset.idc.name }}</b></td> <td><b>{{ asset.idc.name }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Cabinet no' %}:</td> <td>{% trans 'Cabinet number' %}:</td>
<td><b>{{ asset.cabinet_no }}</b></td> <td><b>{{ asset.cabinet_no }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Cabinet pos' %}:</td> <td>{% trans 'Cabinet position' %}:</td>
<td><b>{{ asset.cabinet_pos }}</b></td> <td><b>{{ asset.cabinet_pos }}</b></td>
</tr> </tr>
<tr> <tr>
@ -185,7 +185,7 @@
</span></td> </span></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Rrefresh hardware' %}:</td> <td>{% trans 'Refresh hardware' %}:</td>
<td> <td>
<span class="pull-right"> <span class="pull-right">
<button type="button" class="btn btn-primary btn-xs" id="btn_refresh_asset" style="width: 54px">{% trans 'Refresh' %}</button> <button type="button" class="btn btn-primary btn-xs" id="btn_refresh_asset" style="width: 54px">{% trans 'Refresh' %}</button>
@ -224,7 +224,7 @@
</tr> </tr>
<tr> <tr>
<td colspan="2" class="no-borders"> <td colspan="2" class="no-borders">
<button type="button" class="btn btn-info btn-sm" id="btn_add_user_group">{% trans 'Join' %}</button> <button type="button" class="btn btn-info btn-sm" id="btn_add_user_group">{% trans 'Confirm' %}</button>
</td> </td>
</tr> </tr>
</form> </form>
@ -251,7 +251,7 @@
<form> <form>
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td colspan="2"> <td colspan="2">
<select data-placeholder="{% trans 'Select system user' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> <select data-placeholder="{% trans 'Select system users' %}" class="select2" style="width: 100%" multiple="" tabindex="4">
{% for system_user in system_users_remain %} {% for system_user in system_users_remain %}
<option value="{{ system_user.id }}" id="opt_{{ system_user.id }}">{{ system_user.name }}</option> <option value="{{ system_user.id }}" id="opt_{{ system_user.id }}">{{ system_user.name }}</option>
{% endfor %} {% endfor %}
@ -260,7 +260,7 @@
</tr> </tr>
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td colspan="2"> <td colspan="2">
<button type="button" class="btn btn-warning btn-sm btn-system-user">{% trans 'Associate' %}</button> <button type="button" class="btn btn-warning btn-sm btn-system-user">{% trans 'Confirm' %}</button>
</td> </td>
</tr> </tr>
</form> </form>
@ -371,7 +371,7 @@ $(document).ready(function () {
var body = { var body = {
'is_active': checked 'is_active': checked
}; };
var success = '{% trans "Update Successfully!" %}'; var success = '{% trans "Update successfully!" %}';
var status = $(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").text(); var status = $(".ibox-content > table > tbody > tr:nth-child(13) > td:last >b").text();
APIUpdateAttr({ APIUpdateAttr({
url: the_url, url: the_url,

View File

@ -101,12 +101,12 @@ $(document).ready(function(){
closeOnConfirm: false closeOnConfirm: false
}, function() { }, function() {
var success = function() { var success = function() {
var msg = "{% trans 'Group Deleted.' %}"; var msg = "{% trans 'Group deleted' %}";
swal("{% trans 'Group Delete' %}", msg, "success"); swal("{% trans 'Group Delete' %}", msg, "success");
$('#asset_groups_list_table').DataTable().ajax.reload(); $('#asset_groups_list_table').DataTable().ajax.reload();
}; };
var fail = function() { var fail = function() {
var msg = "{% trans 'Group Deleting failed.' %}"; var msg = "{% trans 'Group deleting failed.' %}";
swal("{% trans 'Group Delete' %}", msg, "error"); swal("{% trans 'Group Delete' %}", msg, "error");
}; };
var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list);

View File

@ -81,7 +81,7 @@
<div class="col-sm-5" style="padding-left: 0;padding-right: 0"> <div class="col-sm-5" style="padding-left: 0;padding-right: 0">
<div class="panel panel-primary"> <div class="panel panel-primary">
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Attach assets to IDC ' %} <i class="fa fa-info-circle"></i> {% trans 'Add assets to' %} {{ idc.name }}
</div> </div>
<div class="panel-body"> <div class="panel-body">
<table class="table"> <table class="table">
@ -98,7 +98,7 @@
</tr> </tr>
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td colspan="2"> <td colspan="2">
<button type="button" class="btn btn-primary btn-sm btn-asset-attach">{% trans 'Attach Assets' %}</button> <button type="button" class="btn btn-primary btn-sm btn-asset-attach">{% trans 'Confirm' %}</button>
</td> </td>
</tr> </tr>
</form> </form>

View File

@ -92,7 +92,7 @@ $(document).ready(function(){
function doDelete() { function doDelete() {
swal({ swal({
title: "{% trans 'Are you sure?' %}", title: "{% trans 'Are you sure?' %}",
text: "{% trans 'This will delete the selected idc !!!' %}", text: "{% trans 'This will delete the selected idc' %}",
type: "warning", type: "warning",
showCancelButton: true, showCancelButton: true,
confirmButtonColor: "#DD6B55", confirmButtonColor: "#DD6B55",

View File

@ -17,7 +17,7 @@
<a href="{% url 'assets:system-user-detail' pk=system_user.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a> <a href="{% url 'assets:system-user-detail' pk=system_user.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li> </li>
<li class="active"><a href="{% url 'assets:system-user-asset' pk=system_user.id %}" class="text-center"> <li class="active"><a href="{% url 'assets:system-user-asset' pk=system_user.id %}" class="text-center">
<i class="fa fa-bar-chart-o"></i> {% trans 'Associate assets and asset groups' %}</a> <i class="fa fa-bar-chart-o"></i> {% trans 'Attached assets' %}</a>
</li> </li>
</ul> </ul>
</div> </div>
@ -25,7 +25,7 @@
<div class="col-sm-7" style="padding-left: 0;"> <div class="col-sm-7" style="padding-left: 0;">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span style="float: left">{% trans 'Assets attached of ' %} <b>{{ system_user.name }} </b><span class="badge">{{ paginator.count }}</span></span> <span style="float: left">{% trans 'Assets of ' %} <b>{{ system_user.name }} </b><span class="badge">{{ paginator.count }}</span></span>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
@ -52,19 +52,19 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{# {% for asset in page_obj %}#} {% for asset in page_obj %}
{# <tr>#} <tr>
{# <td>{{ asset.hostname }}</td>#} <td>{{ asset.hostname }}</td>
{# <td>{{ asset.ip }}</td>#} <td>{{ asset.ip }}</td>
{# <td>{{ asset.port }}</td>#} <td>{{ asset.port }}</td>
{# <td>#} <td>
{# <i class="fa fa-check text-navy"></i>#} <i class="fa fa-check text-navy"></i>
{# </td>#} </td>
{# <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>#} <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>#} </td>
{# </tr>#} </tr>
{# {% endfor %}#} {% endfor %}
</tbody> </tbody>
</table> </table>
{# <div class="row">#} {# <div class="row">#}
@ -93,7 +93,7 @@
</tr> </tr>
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td colspan="2"> <td colspan="2">
<button type="button" class="btn btn-primary btn-sm btn-add-asset2system-user">{% trans 'Attach Asset' %}</button> <button type="button" class="btn btn-primary btn-sm btn-add-asset2system-user">{% trans 'Confirm' %}</button>
</td> </td>
</tr> </tr>
</form> </form>

View File

@ -1,134 +0,0 @@
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block custom_head_css_js %}
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="panel-options">
<ul class="nav nav-tabs">
<li>
<a href="{% url 'assets:system-user-detail' pk=system_user.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li>
<li><a href="{% url 'assets:system-user-asset' pk=system_user.id %}" class="text-center">
<i class="fa fa-bar-chart-o"></i> {% trans 'Associate assets' %}</a>
</li>
<li class="active">
<a href="{% url 'assets:system-user-asset-group' pk=system_user.id %}" class="text-center">
<i class="fa fa-bar-chart-o"></i> {% trans 'Associate asset groups' %}</a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-7" style="padding-left: 0;">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span style="float: left">{% trans 'Asset list of ' %} <b>{{ admin_user.name }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<table class="table table-hover">
<thead>
<tr>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Asset num' %}</th>
<th>{% trans 'Unavailable num' %}</th>
<th>{% trans 'Comment' %}</th>
</tr>
</thead>
<tbody>
{% for asset_group in page_obj %}
<tr>
<td>{{ asset_group.name }}</td>
<td>{{ asset_group_group.assets.count }}</td>
<td>{{ asset_group_group.assets.count }}</td>
<td>{{ asset_group.comment|truncatewords:4 }}</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 'Add asset group to this system user' %}
</div>
<div class="panel-body">
<table class="table">
<tbody>
<form>
<tr class="no-borders-tr">
<td colspan="2">
<select data-placeholder="{% trans 'Select asset group' %}" class="select2" style="width: 100%" multiple="" tabindex="4">
{% 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-primary btn-sm">{% trans 'Add' %}</button>
</td>
</tr>
</form>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% 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>
{% endblock %}

View File

@ -18,7 +18,7 @@
</li> </li>
<li> <li>
<a href="{% url 'assets:system-user-asset' pk=system_user.id %}" class="text-center"> <a href="{% url 'assets:system-user-asset' pk=system_user.id %}" class="text-center">
<i class="fa fa-bar-chart-o"></i> {% trans 'Associate assets and asset groups' %} <i class="fa fa-bar-chart-o"></i> {% trans 'Attached assets' %}
</a> </a>
</li> </li>
<li class="pull-right"> <li class="pull-right">
@ -62,15 +62,7 @@
</tr> </tr>
<tr> <tr>
<td>{% trans 'Auto push' %}:</td> <td>{% trans 'Auto push' %}:</td>
<td><b>{{ system_user.protocol }}</b></td> <td><b>{{ system_user.auto_push|yesno:"Yes,No,Unknown" }}</b></td>
</tr>
<tr>
<td>{% trans 'Auto update' %}:</td>
<td><b>{{ system_user.auto_update }}</b></td>
</tr>
<tr>
<td>{% trans 'As default' %}:</td>
<td><b>{{ system_user.protocol }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Sudo' %}:</td> <td>{% trans 'Sudo' %}:</td>
@ -121,7 +113,7 @@
<table class="table"> <table class="table">
<tbody> <tbody>
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td width="50%">{% trans 'Get mannual install script' %}:</td> <td width="50%">{% trans 'Get manual install script' %}:</td>
<td> <td>
<span style="float: right"> <span style="float: right">
<button type="button" class="btn btn-primary btn-xs" style="width: 54px">{% trans 'Get' %}</button> <button type="button" class="btn btn-primary btn-xs" style="width: 54px">{% trans 'Get' %}</button>

View File

@ -49,10 +49,10 @@ class AdminUserCreateView(AdminUserRequiredMixin,
def get_success_message(self, cleaned_data): def get_success_message(self, cleaned_data):
success_message = _( success_message = _(
'Create admin user <a href="%s">%s</a> successfully.' % ( 'Create admin user <a href="{url}">{name}</a> successfully.'.format(
reverse_lazy('assets:admin-user-detail', url=reverse_lazy('assets:admin-user-detail',
kwargs={'pk': self.object.pk}), kwargs={'pk': self.object.pk}),
self.object.name, name=self.object.name,
)) ))
return success_message return success_message

View File

@ -50,16 +50,13 @@ class SystemUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVi
kwargs.update(context) kwargs.update(context)
return super(SystemUserCreateView, self).get_context_data(**kwargs) return super(SystemUserCreateView, self).get_context_data(**kwargs)
def form_invalid(self, form):
print(form.errors)
return super(SystemUserCreateView, self).form_invalid(form)
def get_success_message(self, cleaned_data): def get_success_message(self, cleaned_data):
success_message = _('Create system user <a href="%s">%s</a> successfully.' % url = reverse_lazy('assets:system-user-detail',
( kwargs={'pk': self.object.pk}),
reverse_lazy('assets:system-user-detail', kwargs={'pk': self.object.pk}), success_message = _(
self.object.name, 'Create system user <a href="{url}">{name}</a> '
)) 'successfully.'.format(url=url, name=self.object.name)
)
return success_message return success_message
@ -78,7 +75,8 @@ class SystemUserUpdateView(AdminUserRequiredMixin, UpdateView):
return super(SystemUserUpdateView, self).get_context_data(**kwargs) return super(SystemUserUpdateView, self).get_context_data(**kwargs)
def get_success_url(self): def get_success_url(self):
success_url = reverse_lazy('assets:system-user-detail', kwargs={'pk': self.object.pk}) success_url = reverse_lazy('assets:system-user-detail',
kwargs={'pk': self.object.pk})
return success_url return success_url

View File

@ -112,6 +112,10 @@ SESSION_COOKIE_DOMAIN = CONFIG.SESSION_COOKIE_DOMAIN or None
CSRF_COOKIE_DOMAIN = CONFIG.CSRF_COOKIE_DOMAIN or None CSRF_COOKIE_DOMAIN = CONFIG.CSRF_COOKIE_DOMAIN or None
SESSION_COOKIE_AGE = CONFIG.SESSION_COOKIE_AGE or 3600*24 SESSION_COOKIE_AGE = CONFIG.SESSION_COOKIE_AGE or 3600*24
print(SESSION_COOKIE_DOMAIN, CSRF_COOKIE_DOMAIN)
MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
# Database # Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases # https://docs.djangoproject.com/en/1.10/ref/settings/#databases
@ -327,7 +331,7 @@ CACHES = {
CAPTCHA_IMAGE_SIZE = (80, 33) CAPTCHA_IMAGE_SIZE = (80, 33)
CAPTCHA_FOREGROUND_COLOR = '#001100' CAPTCHA_FOREGROUND_COLOR = '#001100'
CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots',) CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots',)
CAPTCHA_TEST_MODE = CONFIG.CAPTCHA_TEST_MODE
COMMAND_STORE_BACKEND = 'audits.backends.command.db' COMMAND_STORE_BACKEND = 'audits.backends.command.db'
RECORD_STORE_BACKEND = 'audits.backends.record.db' RECORD_STORE_BACKEND = 'audits.backends.record.db'
CAPTCHA_TEST_MODE = CONFIG.CAPTCHA_TEST_MODE

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,7 @@ class Task(models.Model):
timedelta = models.FloatField(default=0.0, verbose_name=_('Time'), null=True) timedelta = models.FloatField(default=0.0, verbose_name=_('Time'), null=True)
is_finished = models.BooleanField(default=False, verbose_name=_('Is finished')) is_finished = models.BooleanField(default=False, verbose_name=_('Is finished'))
is_success = models.BooleanField(default=False, verbose_name=_('Is success')) is_success = models.BooleanField(default=False, verbose_name=_('Is success'))
assets = models.TextField(blank=True, null=True, verbose_name=_('Assets for id')) # Asset inventory may be change assets = models.TextField(blank=True, null=True, verbose_name=_('Assets id')) # Asset inventory may be change
_modules_args = models.TextField(blank=True, null=True, verbose_name=_('Task module and args json format')) _modules_args = models.TextField(blank=True, null=True, verbose_name=_('Task module and args json format'))
pattern = models.CharField(max_length=64, default='all', verbose_name=_('Task run pattern')) pattern = models.CharField(max_length=64, default='all', verbose_name=_('Task run pattern'))
result = models.TextField(blank=True, null=True, verbose_name=_('Task raw result')) result = models.TextField(blank=True, null=True, verbose_name=_('Task raw result'))

View File

@ -81,7 +81,7 @@
{% endif %} {% endif %}
</tr> </tr>
<tr> <tr>
<td>{% trans 'Assets ' %}:</td> <td>{% trans 'assets' %}:</td>
<td> <td>
<b> <b>
{% for asset in object.total_assets %} {% for asset in object.total_assets %}

View File

@ -106,7 +106,7 @@
<form> <form>
<tr class="no-borders-tr"> <tr class="no-borders-tr">
<td colspan="2"> <td colspan="2">
<select data-placeholder="{% trans 'Select asset ' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> <select data-placeholder="{% trans 'Select assets' %}" class="select2" style="width: 100%" multiple="" tabindex="4">
{% for asset in asset_remain %} {% for asset in asset_remain %}
<option value="{{ asset.id }}">{{ asset.hostname }}: {{ asset.ip }}</option> <option value="{{ asset.id }}">{{ asset.hostname }}: {{ asset.ip }}</option>
{% endfor %} {% endfor %}

View File

@ -80,11 +80,11 @@ class AssetPermissionCreateView(AdminUserRequiredMixin,
return super(AssetPermissionCreateView, self).get_context_data(**kwargs) return super(AssetPermissionCreateView, self).get_context_data(**kwargs)
def get_success_message(self, cleaned_data): def get_success_message(self, cleaned_data):
url = reverse_lazy('perms:asset-permission-detail',
kwargs={'pk': self.object.pk})
success_message = _( success_message = _(
'Create asset permission <a href="%s"> %s </a> ' 'Create asset permission <a href="{url}"> {name} </a> '
'successfully.' % (reverse_lazy('perms:asset-permission-detail', 'successfully.'.format(url=url, name=self.object.name))
kwargs={'pk': self.object.pk}),
self.object.name,))
return success_message return success_message
def form_valid(self, form): def form_valid(self, form):
@ -102,8 +102,9 @@ class AssetPermissionUpdateView(AdminUserRequiredMixin, UpdateView):
model = AssetPermission model = AssetPermission
form_class = AssetPermissionForm form_class = AssetPermissionForm
template_name = 'perms/asset_permission_create_update.html' template_name = 'perms/asset_permission_create_update.html'
success_message = _('Update asset permission ' success_message = _(
'<a href="%s"> %s </a> successfully.') 'Update asset permission <a href="{url}"> {name} </a> successfully.'
)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
@ -113,10 +114,12 @@ class AssetPermissionUpdateView(AdminUserRequiredMixin, UpdateView):
kwargs.update(context) kwargs.update(context)
return super(AssetPermissionUpdateView, self).get_context_data(**kwargs) return super(AssetPermissionUpdateView, self).get_context_data(**kwargs)
def get_success_url(self): def get_success_message(self):
success_url = reverse_lazy('perms:asset-permission-detail', url = reverse_lazy('perms:asset-permission-detail',
kwargs={'pk': self.object.pk}) kwargs={'pk': self.object.pk})
return success_url return self.success_message.format(
url=url, name=self.object.name
)
def form_valid(self, form): def form_valid(self, form):
assets = form.cleaned_data['assets'] assets = form.cleaned_data['assets']

View File

@ -1,5 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% load i18n %}
{% block custom_head_css_js %} {% block custom_head_css_js %}
<link href="{% static "css/plugins/dataTables/datatables.min.css" %}" rel="stylesheet"> <link href="{% static "css/plugins/dataTables/datatables.min.css" %}" rel="stylesheet">
<link href="{% static "css/plugins/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css" %}" rel="stylesheet"> <link href="{% static "css/plugins/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css" %}" rel="stylesheet">
@ -40,17 +41,17 @@
<div class="input-group"> <div class="input-group">
<div class="input-group-btn"> <div class="input-group-btn">
<button id='search_btn' type="submit" class="btn btn-sm btn-primary"> <button id='search_btn' type="submit" class="btn btn-sm btn-primary">
搜索 {% trans 'Search' %}
</button> </button>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
</form> </form>
{% endblock %} {% endblock %}
{% block tags_list %}{% endblock %} {# {% block tags_list %}{% endblock %}#}
</div> </div>
{% block table_container %} {% block table_container %}
<table class="table table-striped table-bordered table-hover " id="editable" > <table class="table table-striped table-bordered table-hover" id="editable" >
<thead> <thead>
<tr> <tr>
{% block table_head %} {% endblock %} {% block table_head %} {% endblock %}

View File

@ -1,7 +1,7 @@
{% load i18n %} {% load i18n %}
<li id="index"> <li id="index">
<a href="{% url 'index' %}"> <a href="{% url 'index' %}">
<i class="fa fa-dashboard"></i> <span class="nav-label">{% trans 'Home' %}</span><span class="label label-info pull-right"></span> <i class="fa fa-dashboard"></i> <span class="nav-label">{% trans 'Dashboard' %}</span><span class="label label-info pull-right"></span>
</a> </a>
</li> </li>
<li id="users"> <li id="users">

View File

@ -16,7 +16,6 @@
<body> <body>
<div id="wrapper"> <div id="wrapper">
{% include '_left_side_bar.html' %} {% include '_left_side_bar.html' %}
<div id="page-wrapper" class="gray-bg"> <div id="page-wrapper" class="gray-bg">
{% include '_header_bar.html' %} {% include '_header_bar.html' %}

View File

@ -131,14 +131,6 @@ class UserGroupForm(forms.ModelForm):
} }
# class UserInfoForm(forms.Form):
# name = forms.CharField(max_length=20, label=_('name'))
# avatar = forms.ImageField(label=_('avatar'), required=False)
# wechat = forms.CharField(max_length=30, label=_('wechat'), required=False)
# phone = forms.CharField(max_length=20, label=_('phone'), required=False)
# enable_otp = forms.BooleanField(required=False, label=_('enable otp'))
class UserPrivateAssetPermissionForm(forms.ModelForm): class UserPrivateAssetPermissionForm(forms.ModelForm):
def save(self, commit=True): def save(self, commit=True):
self.instance = super(UserPrivateAssetPermissionForm, self)\ self.instance = super(UserPrivateAssetPermissionForm, self)\

View File

@ -17,7 +17,8 @@ __all__ = ['UserGroup']
class UserGroup(NoDeleteModelMixin): class UserGroup(NoDeleteModelMixin):
name = models.CharField(max_length=128, verbose_name=_('Name')) name = models.CharField(max_length=128, verbose_name=_('Name'))
comment = models.TextField(blank=True, verbose_name=_('Comment')) comment = models.TextField(blank=True, verbose_name=_('Comment'))
date_created = models.DateTimeField(auto_now_add=True, null=True) date_created = models.DateTimeField(auto_now_add=True, null=True,
verbose_name=_('Date created'))
created_by = models.CharField(max_length=100) created_by = models.CharField(max_length=100)
def __unicode__(self): def __unicode__(self):

View File

@ -18,7 +18,7 @@
<div class="form-group"> <div class="form-group">
<label for="groups" class="col-sm-2 control-label">{% trans 'Groups' %}</label> <label for="groups" class="col-sm-2 control-label">{% trans 'Groups' %}</label>
<div class="col-sm-9" id="select2-container"> <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> <select name="groups" id="select2_groups" data-placeholder="{% trans 'Select groups' %}" class="select2 form-control m-b" multiple>
{% for group in groups %} {% for group in groups %}
<option value="{{ group.id }}">{{ group.name }}</option> <option value="{{ group.id }}">{{ group.name }}</option>
{% endfor %} {% endfor %}

View File

@ -268,7 +268,7 @@ $(document).ready(function() {
var body = { var body = {
'is_active': checked 'is_active': checked
}; };
var success = '{% trans "Update Successfully!" %}'; var success = '{% trans "Update successfully!" %}';
APIUpdateAttr({ APIUpdateAttr({
url: the_url, url: the_url,
body: JSON.stringify(body), body: JSON.stringify(body),
@ -281,7 +281,7 @@ $(document).ready(function() {
var body = { var body = {
'enable_otp': checked 'enable_otp': checked
}; };
var success = '{% trans "Update Successfully!" %}'; var success = '{% trans "Update successfully!" %}';
APIUpdateAttr({ APIUpdateAttr({
url: the_url, url: the_url,
body: JSON.stringify(body), body: JSON.stringify(body),
@ -320,7 +320,7 @@ $(document).ready(function() {
var body = {}; var body = {};
var success = function() { var success = function() {
var msg = "{% trans "An e-mail has been sent to the user\'s mailbox." %}"; var msg = "{% trans "An e-mail has been sent to the user\'s mailbox." %}";
swal("{% trans 'Password-Reset' %}", msg, "success"); swal("{% trans 'Reset password' %}", msg, "success");
}; };
APIUpdateAttr({ APIUpdateAttr({
url: the_url, url: the_url,
@ -330,7 +330,7 @@ $(document).ready(function() {
} }
swal({ swal({
title: "{% trans 'Are you sure?' %}", title: "{% trans 'Are you sure?' %}",
text: "{% trans 'This will reset the user\'s password. A password-reset email will be sent to the user\'s mailbox.' %}", text: "{% trans "This will reset the user's password. A password-reset email will be sent to the user\'s mailbox." %}",
type: "warning", type: "warning",
showCancelButton: true, showCancelButton: true,
confirmButtonColor: "#DD6B55", confirmButtonColor: "#DD6B55",
@ -345,7 +345,7 @@ $(document).ready(function() {
var body = {}; var body = {};
var success = function() { var success = function() {
var msg = "{% trans 'The reset-ssh-public-key E-mail has been sent successfully. Please inform the user to update his new ssh public key.' %}"; var msg = "{% trans 'The reset-ssh-public-key E-mail has been sent successfully. Please inform the user to update his new ssh public key.' %}";
swal("{% trans 'SSH-Public-Key Reset' %}", msg, "success"); swal("{% trans 'Reset SSH public key' %}", msg, "success");
}; };
APIUpdateAttr({ APIUpdateAttr({
url: the_url, url: the_url,

View File

@ -42,7 +42,7 @@
<div class="form-group"> <div class="form-group">
<div class="col-sm-4 col-sm-offset-2"> <div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Cancel' %}</button> <button class="btn btn-white" type="reset">{% trans 'Cancel' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'confirm' %}</button> <button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Confirm' %}</button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -19,7 +19,7 @@
<div class="panel-options"> <div class="panel-options">
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li class="active"> <li class="active">
<a href="{% url 'users:user-group-detail' pk=user_group.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User Group Detail' %} </a> <a href="{% url 'users:user-group-detail' pk=user_group.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User group detail' %} </a>
</li> </li>
<li> <li>
<a href="{% url 'users:user-group-asset-permission' pk=user_group.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a> <a href="{% url 'users:user-group-asset-permission' pk=user_group.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>

View File

@ -2,7 +2,7 @@
{% load i18n static %} {% load i18n static %}
{% block table_search %}{% endblock %} {% block table_search %}{% endblock %}
{% block table_container %} {% block table_container %}
<div class="pull-left m-r-5"><a href="{% url 'users:user-group-create' %}" class="btn btn-sm btn-primary ">{% trans "Add User Group" %}</a></div> <div class="pull-left m-r-5"><a href="{% url 'users:user-group-create' %}" class="btn btn-sm btn-primary ">{% trans "Create user group" %}</a></div>
<table class="table table-striped table-bordered table-hover " id="group_list_table" > <table class="table table-striped table-bordered table-hover " id="group_list_table" >
<thead> <thead>
<tr> <tr>
@ -10,7 +10,7 @@
<input id="" type="checkbox" class="ipt_check_all"> <input id="" type="checkbox" class="ipt_check_all">
</th> </th>
<th class="text-center">{% trans 'Name' %}</th> <th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'User Amount' %}</th> <th class="text-center">{% trans 'User count' %}</th>
<th class="text-center">{% trans 'Comment' %}</th> <th class="text-center">{% trans 'Comment' %}</th>
<th class="text-center">{% trans 'Action' %}</th> <th class="text-center">{% trans 'Action' %}</th>
</tr> </tr>
@ -61,6 +61,7 @@ $(document).ready(function() {
ajax_url: '{% url "api-users:user-group-list" %}', ajax_url: '{% url "api-users:user-group-list" %}',
columns: [{data: function(){return ""}}, {data: "name" }, {data: "user_amount"}, columns: [{data: function(){return ""}}, {data: "name" }, {data: "user_amount"},
{data: "comment"}, {data: "id" }], {data: "comment"}, {data: "id" }],
order: [4, 'asc'],
op_html: $('#actions').html() op_html: $('#actions').html()
}; };
jumpserver.initDataTable(options); jumpserver.initDataTable(options);

View File

@ -141,7 +141,7 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Reset public key' %}:</td> <td>{% trans 'Reset SSH public key' %}:</td>
<td> <td>
<span class="pull-right"> <span class="pull-right">
<a type="button" class="btn btn-primary btn-xs" style="width: 54px" href="{% url 'users:user-pubkey-update' %}">{% trans 'Reset' %}</a> <a type="button" class="btn btn-primary btn-xs" style="width: 54px" href="{% url 'users:user-pubkey-update' %}">{% trans 'Reset' %}</a>

View File

@ -9,6 +9,7 @@ from django.views.generic import ListView
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.views.generic.edit import CreateView, UpdateView, FormMixin from django.views.generic.edit import CreateView, UpdateView, FormMixin
from django.views.generic.detail import DetailView, SingleObjectMixin from django.views.generic.detail import DetailView, SingleObjectMixin
from django.contrib.messages.views import SuccessMessageMixin
from common.utils import get_logger from common.utils import get_logger
from perms.models import AssetPermission from perms.models import AssetPermission
@ -31,11 +32,12 @@ class UserGroupListView(AdminUserRequiredMixin, TemplateView):
return context return context
class UserGroupCreateView(AdminUserRequiredMixin, CreateView): class UserGroupCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
model = UserGroup model = UserGroup
form_class = forms.UserGroupForm form_class = forms.UserGroupForm
template_name = 'users/user_group_create_update.html' template_name = 'users/user_group_create_update.html'
success_url = reverse_lazy('users:user-group-list') success_url = reverse_lazy('users:user-group-list')
success_message = '<a href={url}> {name} </a> was created successfully'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(UserGroupCreateView, self).get_context_data(**kwargs) context = super(UserGroupCreateView, self).get_context_data(**kwargs)
@ -54,6 +56,14 @@ class UserGroupCreateView(AdminUserRequiredMixin, CreateView):
user_group.save() user_group.save()
return super(UserGroupCreateView, self).form_valid(form) return super(UserGroupCreateView, self).form_valid(form)
def get_success_message(self, cleaned_data):
url = reverse_lazy('users:user-group-detail',
kwargs={'pk': self.object.id}
)
return self.success_message.format(
url=url, name=self.object.name
)
class UserGroupUpdateView(AdminUserRequiredMixin, UpdateView): class UserGroupUpdateView(AdminUserRequiredMixin, UpdateView):
model = UserGroup model = UserGroup
@ -68,7 +78,7 @@ class UserGroupUpdateView(AdminUserRequiredMixin, UpdateView):
group_users = [user.id for user in self.object.users.all()] group_users = [user.id for user in self.object.users.all()]
context.update({ context.update({
'app': _('Users'), 'app': _('Users'),
'action': _('Update User Group'), 'action': _('Update user group'),
'users': users, 'users': users,
'group_users': group_users 'group_users': group_users
}) })

View File

@ -63,7 +63,7 @@ class UserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
form_class = forms.UserCreateUpdateForm form_class = forms.UserCreateUpdateForm
template_name = 'users/user_create.html' template_name = 'users/user_create.html'
success_url = reverse_lazy('users:user-list') success_url = reverse_lazy('users:user-list')
success_message = _('Create user <a href="%s">%s</a> successfully.') success_message = _('Create user <a href="{url}">{name}</a> successfully.')
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(UserCreateView, self).get_context_data(**kwargs) context = super(UserCreateView, self).get_context_data(**kwargs)
@ -78,9 +78,9 @@ class UserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
return super(UserCreateView, self).form_valid(form) return super(UserCreateView, self).form_valid(form)
def get_success_message(self, cleaned_data): def get_success_message(self, cleaned_data):
return self.success_message % ( url = reverse_lazy('users:user-detail', kwargs={'pk': self.object.pk})
reverse_lazy('users:user-detail', kwargs={'pk': self.object.pk}), return self.success_message.format(
self.object.name, url=url, name=self.object.name
) )
@ -331,15 +331,15 @@ class UserProfileUpdateView(LoginRequiredMixin, UpdateView):
model = User model = User
form_class = forms.UserProfileForm form_class = forms.UserProfileForm
success_url = reverse_lazy('users:user-profile') success_url = reverse_lazy('users:user-profile')
success_message = _('Create user <a href="%s">%s</a> successfully.') success_message = _('Create user <a href="{url}">{name}</a> successfully.')
def get_object(self, queryset=None): def get_object(self, queryset=None):
return self.request.user return self.request.user
def get_success_message(self, cleaned_data): def get_success_message(self, cleaned_data):
return self.success_message % ( url = reverse_lazy('users:user-detail', kwargs={'pk': self.object.pk})
reverse_lazy('users:user-detail', kwargs={'pk': self.object.pk}), return self.success_message.format(
self.object.name, url=url, name=self.object.name
) )
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):

View File

@ -1 +1 @@
ibtiff4-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk libtiff4-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk