From 243eedc4f9c63882ac2ec5b8b80f3c97e5d10a00 Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 18 Jan 2021 17:11:30 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=B7=A5=E5=8D=95bod?= =?UTF-8?q?y=20html=E6=98=BE=E7=A4=BA=E6=A0=BC=E5=BC=8F=E5=8F=8A=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/zh/LC_MESSAGES/django.mo | Bin 62041 -> 63233 bytes apps/locale/zh/LC_MESSAGES/django.po | 199 ++++++++++++++++------ apps/tickets/handler/apply_application.py | 32 ++-- apps/tickets/handler/apply_asset.py | 36 ++-- apps/tickets/handler/base.py | 66 ++++--- apps/tickets/handler/login_confirm.py | 8 +- apps/tickets/signals_handler/ticket.py | 18 -- apps/tickets/utils.py | 39 ++--- 8 files changed, 231 insertions(+), 167 deletions(-) diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index df0dea23028d5c12270fb00e674a8c1db58050d8..62f5281f5327828c2a26dd4c340d62fee69d9e54 100644 GIT binary patch delta 20908 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≥7HFe4U8`)cq^jX3C7+|K92L{mCn4+3;lVomg;t=agIf)+bciwWe$Q z-sI`i{<-s%=ds)WdF&2xp2x}QZ~LEYy4z0Lx9eaQ&z%YH-aa%vdH1^H*$a|qEKT0O zuR@?3rL3BMXU$^wMRzmq?cdtBFMTrky(y`4r~M}xXdj9HKYO~*#H~H+?j(&pc+4-M z(bT)Wdzm|5?%bSA1x7%EYafa_{X{`c(4Ui`*?)m*kcEQkHFYyCkek z4XpBf&uP=n+?6t6V%mh>`%Y`|KBJ^PsV6e|+vno;p(VHWY;yOLH1ekfK9z2Lv?^s; z{H;9`$fqparl;jS&kBJl%h%nWzUle7xgU|7_t%wY$n$Q=yLa4Pljt6dyE7+s5|4d< R%F1=A%Vs5QyT38R{{g$@v-JP~ delta 19218 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\n" "Language-Team: JumpServer team\n" @@ -2839,6 +2839,137 @@ msgstr "拒绝" msgid "Closed" msgstr "关闭" +#: tickets/handler/apply_application.py:55 +msgid "Applied category" +msgstr "申请的种类" + +#: tickets/handler/apply_application.py:56 +msgid "Applied type" +msgstr "申请的类型" + +#: tickets/handler/apply_application.py:57 +msgid "Applied application group" +msgstr "申请的应用组" + +#: tickets/handler/apply_application.py:58 tickets/handler/apply_asset.py:59 +msgid "Applied system user group" +msgstr "申请的系统用户组" + +#: tickets/handler/apply_application.py:59 tickets/handler/apply_asset.py:61 +msgid "Applied date start" +msgstr "申请的开始日期" + +#: tickets/handler/apply_application.py:60 tickets/handler/apply_asset.py:62 +msgid "Applied date expired" +msgstr "申请的失效日期" + +#: tickets/handler/apply_application.py:75 +msgid "Approved applications" +msgstr "批准的应用" + +#: tickets/handler/apply_application.py:76 tickets/handler/apply_asset.py:79 +msgid "Approved system users" +msgstr "批准的系统用户" + +#: tickets/handler/apply_application.py:77 tickets/handler/apply_asset.py:81 +msgid "Approved date start" +msgstr "批准的开始日期" + +#: tickets/handler/apply_application.py:78 tickets/handler/apply_asset.py:82 +msgid "Approved date expired" +msgstr "批准的失效日期" + +#: tickets/handler/apply_application.py:95 tickets/handler/apply_asset.py:98 +msgid "Created by ticket ({}) ({})" +msgstr "通过工单创建 ({}) ({})" + +#: tickets/handler/apply_application.py:99 tickets/handler/apply_asset.py:102 +msgid "" +"Created by the ticket, ticket title: {}, ticket applicant: {}, ticket " +"processor: {}, ticket ID: {}" +msgstr "" +"通过工单创建, 工单标题: {}, 工单申请人: {}, 工单处理人: {}, 工单 ID: {}" + +#: tickets/handler/apply_asset.py:57 +msgid "Applied IP group" +msgstr "申请的IP组" + +#: tickets/handler/apply_asset.py:58 +msgid "Applied hostname group" +msgstr "申请的主机名组" + +#: tickets/handler/apply_asset.py:60 +msgid "Applied actions" +msgstr "申请的动作" + +#: tickets/handler/apply_asset.py:78 +msgid "Approved assets" +msgstr "批准的资产" + +#: tickets/handler/apply_asset.py:80 +msgid "Approved actions" +msgstr "批准的动作" + +#: tickets/handler/base.py:62 +msgid "User {} {} the ticket" +msgstr "用户 {} {} 这个工单" + +#: tickets/handler/base.py:89 +msgid "Ticket basic info" +msgstr "工单基本信息" + +#: tickets/handler/base.py:90 +msgid "Ticket title" +msgstr "工单标题" + +#: tickets/handler/base.py:91 +msgid "Ticket type" +msgstr "工单类型" + +#: tickets/handler/base.py:92 +msgid "Ticket applicant" +msgstr "工单申请人" + +#: tickets/handler/base.py:93 +msgid "Ticket assignees" +msgstr "工单受理人" + +#: tickets/handler/base.py:94 +msgid "Ticket processor" +msgstr "工单处理人" + +#: tickets/handler/base.py:94 +msgid "No" +msgstr "无" + +#: tickets/handler/base.py:95 +msgid "Ticket action" +msgstr "工单动作" + +#: tickets/handler/base.py:96 +msgid "Ticket status" +msgstr "工单状态" + +#: tickets/handler/base.py:114 +msgid "Ticket applied info" +msgstr "工单申请信息" + +#: tickets/handler/base.py:124 +msgid "Ticket approved info" +msgstr "工单批准信息" + +#: tickets/handler/login_confirm.py:16 +msgid "Applied login IP" +msgstr "申请的登录IP" + +#: tickets/handler/login_confirm.py:17 +msgid "Applied login city" +msgstr "申请的登录城市" + +#: tickets/handler/login_confirm.py:18 +msgid "Applied login datetime" +msgstr "申请的登录日期" + #: tickets/models/comment.py:19 msgid "User display name" msgstr "用户显示名称" @@ -2974,65 +3105,23 @@ msgstr "所有受理人都不属于组织 `{}` 下的管理员" #: tickets/utils.py:21 msgid "New Ticket: {} ({})" -msgstr "新建工单: {} ({})" +msgstr "新工单: {} ({})" -#: tickets/utils.py:26 -#, python-brace-format -msgid "" -"
\n" -"

Your has a new ticket

\n" -"
\n" -" Ticket: \n" -"
\n" -" {body}\n" -"
\n" -" click here to review \n" -"
\n" -"
\n" -" " -msgstr "" -"
\n" -"

你有一个新工单

\n" -"
\n" -" 工单: \n" -"
\n" -" {body}\n" -"
\n" -" 点击查看 \n" -"
\n" -"
\n" -" " +#: tickets/utils.py:33 +msgid "Your has a new ticket, from applicant - {}" +msgstr "你有一个新的工单, 来自申请人 - {}" -#: tickets/utils.py:51 +#: tickets/utils.py:35 +msgid "click here to review" +msgstr "点击查看" + +#: tickets/utils.py:48 msgid "Ticket has processed: {} ({})" msgstr "工单已处理: {} ({})" -#: tickets/utils.py:53 -#, python-brace-format -msgid "" -"\n" -"
\n" -"

Your ticket has been processed

\n" -"
\n" -" Ticket: \n" -"
\n" -" {body}\n" -"
\n" -"
\n" -"
\n" -" " -msgstr "" -"\n" -"
\n" -"

你的工单已被处理

\n" -"
\n" -" 工单: \n" -"
\n" -" {body}\n" -"
\n" -"
\n" -"
\n" -" " +#: tickets/utils.py:57 +msgid "Your ticket has been ({}) processed" +msgstr "你的工单已被 ({}) 处理" #: users/api/user.py:199 msgid "Could not reset self otp, use profile reset instead" diff --git a/apps/tickets/handler/apply_application.py b/apps/tickets/handler/apply_application.py index 28eb82697..d9c72e2bf 100644 --- a/apps/tickets/handler/apply_application.py +++ b/apps/tickets/handler/apply_application.py @@ -1,4 +1,4 @@ -from django.utils.translation import ugettext as __ +from django.utils.translation import ugettext as _ from orgs.utils import tmp_to_org, tmp_to_root_org from applications.models import Application from applications.const import ApplicationCategoryChoices, ApplicationTypeChoices @@ -52,12 +52,12 @@ class Handler(BaseHandler): {}: {}, {}: {}, '''.format( - __('Applied category'), apply_category_display, - __('Applied type'), apply_type_display, - __('Applied application group'), apply_application_group, - __('Applied system user group'), apply_system_user_group, - __('Applied date start'), apply_date_start, - __('Applied date expired'), apply_date_expired, + _('Applied category'), apply_category_display, + _('Applied type'), apply_type_display, + _('Applied application group'), apply_application_group, + _('Applied system user group'), apply_system_user_group, + _('Applied date start'), apply_date_start, + _('Applied date expired'), apply_date_expired, ) return applied_body @@ -72,10 +72,10 @@ class Handler(BaseHandler): {}: {}, {}: {}, '''.format( - __('Approved applications'), approve_applications_display, - __('Approved system users'), approve_system_users_display, - __('Approved date start'), approve_date_start, - __('Approved date expired'), approve_date_expired + _('Approved applications'), approve_applications_display, + _('Approved system users'), approve_system_users_display, + _('Approved date start'), approve_date_start, + _('Approved date expired'), approve_date_expired ) return approved_body @@ -92,10 +92,10 @@ class Handler(BaseHandler): approve_system_users_id = self.ticket.meta.get('approve_system_users', []) approve_date_start = self.ticket.meta.get('approve_date_start') approve_date_expired = self.ticket.meta.get('approve_date_expired') - permission_name = '{}({})'.format( - __('Created by ticket ({})'.format(self.ticket.title)), str(self.ticket.id)[:4] + permission_name = _('Created by ticket ({}) ({})'.format( + self.ticket.title, str(self.ticket.id)[:4]) ) - permission_comment = __( + permission_comment = _( 'Created by the ticket, ' 'ticket title: {}, ' 'ticket applicant: {}, ' @@ -108,10 +108,10 @@ class Handler(BaseHandler): ) permissions_data = { 'id': self.ticket.id, - 'name': permission_name, + 'name': str(permission_name), 'category': apply_category, 'type': apply_type, - 'comment': permission_comment, + 'comment': str(permission_comment), 'created_by': '{}:{}'.format(str(self.__class__.__name__), str(self.ticket.id)), 'date_start': approve_date_start, 'date_expired': approve_date_expired, diff --git a/apps/tickets/handler/apply_asset.py b/apps/tickets/handler/apply_asset.py index 4114c04b3..d01a5c6b1 100644 --- a/apps/tickets/handler/apply_asset.py +++ b/apps/tickets/handler/apply_asset.py @@ -1,5 +1,5 @@ from .base import BaseHandler -from django.utils.translation import ugettext as __ +from django.utils.translation import ugettext as _ from perms.models import AssetPermission, Action from assets.models import Asset, SystemUser @@ -54,12 +54,12 @@ class Handler(BaseHandler): {}: {}, {}: {} '''.format( - __('Applied IP group'), apply_ip_group, - __("Applied hostname group"), apply_hostname_group, - __("Applied system user group"), apply_system_user_group, - __("Applied actions"), apply_actions_display, - __('Applied date start'), apply_date_start, - __('Applied date expired'), apply_date_expired, + _('Applied IP group'), apply_ip_group, + _("Applied hostname group"), apply_hostname_group, + _("Applied system user group"), apply_system_user_group, + _("Applied actions"), apply_actions_display, + _('Applied date start'), apply_date_start, + _('Applied date expired'), apply_date_expired, ) return applied_body @@ -75,11 +75,11 @@ class Handler(BaseHandler): {}: {}, {}: {} '''.format( - __('Approved assets'), approve_assets_display, - __('Approved system users'), approve_system_users_display, - __('Approved actions'), ', '.join(approve_actions_display), - __('Approved date start'), approve_date_start, - __('Approved date expired'), approve_date_expired, + _('Approved assets'), approve_assets_display, + _('Approved system users'), approve_system_users_display, + _('Approved actions'), ', '.join(approve_actions_display), + _('Approved date start'), approve_date_start, + _('Approved date expired'), approve_date_expired, ) return approved_body @@ -95,23 +95,25 @@ class Handler(BaseHandler): approve_actions = self.ticket.meta.get('approve_actions', Action.NONE) approve_date_start = self.ticket.meta.get('approve_date_start') approve_date_expired = self.ticket.meta.get('approve_date_expired') - permission_name = '{}({})'.format( - __('Created by ticket ({})'.format(self.ticket.title)), str(self.ticket.id)[:4] + permission_name = _('Created by ticket ({}) ({})'.format( + self.ticket.title, str(self.ticket.id)[:4]) ) - permission_comment = __( + permission_comment = _( 'Created by the ticket, ' 'ticket title: {}, ' 'ticket applicant: {}, ' 'ticket processor: {}, ' 'ticket ID: {}' ''.format( - self.ticket.title, self.ticket.applicant_display, self.ticket.processor_display, + self.ticket.title, + self.ticket.applicant_display, + self.ticket.processor_display, str(self.ticket.id) ) ) permission_data = { 'id': self.ticket.id, - 'name': permission_name, + 'name': str(permission_name), 'comment': permission_comment, 'created_by': '{}:{}'.format(str(self.__class__.__name__), str(self.ticket.id)), 'actions': approve_actions, diff --git a/apps/tickets/handler/base.py b/apps/tickets/handler/base.py index e1820dc0b..f55b51a37 100644 --- a/apps/tickets/handler/base.py +++ b/apps/tickets/handler/base.py @@ -1,6 +1,8 @@ -from django.utils.translation import ugettext as __ +from django.utils.translation import ugettext as _ from common.utils import get_logger -from tickets.utils import send_ticket_processed_mail_to_applicant +from tickets.utils import ( + send_ticket_processed_mail_to_applicant, send_ticket_applied_mail_to_assignees +) logger = get_logger(__name__) @@ -14,9 +16,11 @@ class BaseHandler(object): # on action def _on_open(self): self.ticket.applicant_display = str(self.ticket.applicant) + self.ticket.assignees_display = [str(assignee) for assignee in self.ticket.assignees.all()] meta_display = getattr(self, '_construct_meta_display_of_open', lambda: {})() self.ticket.meta.update(meta_display) self.ticket.save() + self._send_applied_mail_to_assignees() def _on_approve(self): meta_display = getattr(self, '_construct_meta_display_of_approve', lambda: {})() @@ -41,11 +45,12 @@ class BaseHandler(object): return method() # email + def _send_applied_mail_to_assignees(self): + logger.debug('Send applied email to assignees: {}'.format(self.ticket.assignees_display)) + send_ticket_applied_mail_to_assignees(self.ticket) + def _send_processed_mail_to_applicant(self): - msg = 'Ticket ({}) has processed, send mail to applicant ({})'.format( - self.ticket.title, self.ticket.applicant_display - ) - logger.debug(msg) + logger.debug('Send processed mail to applicant: {}'.format(self.ticket.applicant_display)) send_ticket_processed_mail_to_applicant(self.ticket) # comments @@ -54,13 +59,18 @@ class BaseHandler(object): user_display = str(user) action_display = self.ticket.get_action_display() data = { - 'body': __('User {} {} the ticket'.format(user_display, action_display)), + 'body': _('User {} {} the ticket'.format(user_display, action_display)), 'user': user, 'user_display': user_display } return self.ticket.comments.create(**data) # body + body_html_format = ''' + {}: +
{}
+ ''' + def get_body(self): old_body = self.ticket.meta.get('body') if old_body: @@ -71,9 +81,7 @@ class BaseHandler(object): return basic_body + meta_body def _construct_basic_body(self): - body = ''' - {}: - {}: {}, + basic_body = '''{}: {}, {}: {}, {}: {}, {}: {}, @@ -81,15 +89,15 @@ class BaseHandler(object): {}: {}, {}: {} '''.format( - __("Ticket basic info"), - __('Ticket title'), self.ticket.title, - __('Ticket type'), self.ticket.get_type_display(), - __('Ticket applicant'), self.ticket.applicant_display, - __('Ticket assignees'), self.ticket.assignees_display, - __('Ticket processor'), self.ticket.processor_display, - __('Ticket action'), self.ticket.get_action_display(), - __('Ticket status'), self.ticket.get_status_display() + _('Ticket title'), self.ticket.title, + _('Ticket type'), self.ticket.get_type_display(), + _('Ticket applicant'), self.ticket.applicant_display, + _('Ticket assignees'), self.ticket.assignees_display, + _('Ticket processor'), self.ticket.processor_display or _('No'), + _('Ticket action'), self.ticket.get_action_display(), + _('Ticket status'), self.ticket.get_status_display() ) + body = self.body_html_format.format(_("Ticket basic info"), basic_body) return body def _construct_meta_body(self): @@ -102,21 +110,11 @@ class BaseHandler(object): return body def _base_construct_meta_body_of_open(self): - open_body = ''' - {}: - {} - '''.format( - __('Ticket applied info'), - getattr(self, '_construct_meta_body_of_open', lambda: 'No')() - ) - return open_body + meta_body_of_open = getattr(self, '_construct_meta_body_of_open', lambda: 'No')() + body = self.body_html_format.format(_('Ticket applied info'), meta_body_of_open) + return body def _base_construct_meta_body_of_approve(self): - approve_body = ''' - {}: - {} - '''.format( - __('Ticket approved info'), - getattr(self, '_construct_meta_body_of_approve', lambda: 'No')() - ) - return approve_body + meta_body_of_approve = getattr(self, '_construct_meta_body_of_approve', lambda: 'No')() + body = self.body_html_format.format(_('Ticket approved info'), meta_body_of_approve) + return body diff --git a/apps/tickets/handler/login_confirm.py b/apps/tickets/handler/login_confirm.py index 21419022f..b1d491cfc 100644 --- a/apps/tickets/handler/login_confirm.py +++ b/apps/tickets/handler/login_confirm.py @@ -1,4 +1,4 @@ -from django.utils.translation import ugettext as __ +from django.utils.translation import ugettext as _ from .base import BaseHandler @@ -13,8 +13,8 @@ class Handler(BaseHandler): {}: {}, {}: {} '''.format( - __("Applied login IP"), apply_login_ip, - __("Applied login city"), apply_login_city, - __("Applied login datetime"), apply_login_datetime, + _("Applied login IP"), apply_login_ip, + _("Applied login city"), apply_login_city, + _("Applied login datetime"), apply_login_datetime, ) return applied_body diff --git a/apps/tickets/signals_handler/ticket.py b/apps/tickets/signals_handler/ticket.py index 7e8bc8d5d..aae620295 100644 --- a/apps/tickets/signals_handler/ticket.py +++ b/apps/tickets/signals_handler/ticket.py @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- # from django.dispatch import receiver -from django.db.models.signals import m2m_changed from common.utils import get_logger from tickets.models import Ticket -from tickets.utils import send_ticket_applied_mail_to_assignees from ..signals import post_change_ticket_action @@ -15,19 +13,3 @@ logger = get_logger(__name__) @receiver(post_change_ticket_action, sender=Ticket) def on_post_change_ticket_action(sender, ticket, action, **kwargs): ticket.handler.dispatch(action) - - -@receiver(m2m_changed, sender=Ticket.assignees.through) -def on_ticket_assignees_changed(sender, instance, action, reverse, model, pk_set, **kwargs): - if reverse: - return - if action != 'post_add': - return - logger.debug('Receives ticket and assignees changed signal, ticket: {}'.format(instance.title)) - instance.assignees_display = [str(assignee) for assignee in instance.assignees.all()] - instance.save() - assignees = model.objects.filter(pk__in=pk_set) - assignees_display = [str(assignee) for assignee in assignees] - logger.debug('Send applied email to assignees: {}'.format(assignees_display)) - send_ticket_applied_mail_to_assignees(instance, assignees) - diff --git a/apps/tickets/utils.py b/apps/tickets/utils.py index ebd4c22b8..523d0f102 100644 --- a/apps/tickets/utils.py +++ b/apps/tickets/utils.py @@ -11,10 +11,10 @@ from . import const logger = get_logger(__file__) -def send_ticket_applied_mail_to_assignees(ticket, assignees): - if not assignees: +def send_ticket_applied_mail_to_assignees(ticket): + if not ticket.assignees: logger.debug("Not found assignees, ticket: {}({}), assignees: {}".format( - ticket, str(ticket.id), assignees) + ticket, str(ticket.id), ticket.assignees) ) return @@ -22,25 +22,22 @@ def send_ticket_applied_mail_to_assignees(ticket, assignees): ticket_detail_url = urljoin( settings.SITE_URL, const.TICKET_DETAIL_URL.format(id=str(ticket.id)) ) - message = _( - """
-

Your has a new ticket

+ message = """ +
+

{title} {ticket_detail_url_description}

- Ticket: -
- {body} -
- click here to review + {body}
""".format( + title=_('Your has a new ticket, from applicant - {}').format(str(ticket.applicant)), + ticket_detail_url=ticket_detail_url, + ticket_detail_url_description=_('click here to review'), body=ticket.body.replace('\n', '
'), - ticket_detail_url=ticket_detail_url - ) ) if settings.DEBUG: logger.debug(message) - recipient_list = [assignee.email for assignee in assignees] + recipient_list = [assignee.email for assignee in ticket.assignees.all()] send_mail_async.delay(subject, message, recipient_list, html_message=message) @@ -48,22 +45,18 @@ def send_ticket_processed_mail_to_applicant(ticket): if not ticket.applicant: logger.error("Not found applicant: {}({})".format(ticket.title, ticket.id)) return - subject = _('Ticket has processed: {} ({})').format(ticket.title, ticket.get_type_display()) - message = _( - """ + subject = _('Ticket has processed: {} ({})').format(ticket.title, ticket.processor_display) + message = """
-

Your ticket has been processed

+

{title}

- Ticket: -
- {body} -
+ {body}
""".format( + title=_('Your ticket has been ({}) processed').format(ticket.processor_display), body=ticket.body.replace('\n', '
'), ) - ) if settings.DEBUG: logger.debug(message) recipient_list = [ticket.applicant.email]