示例#1
0
 def display_summary(self, ticket):
     context = {
         'creator': admin_link('creator')(self, ticket) if ticket.creator else ticket.creator_name,
         'created': admin_date('created_at')(ticket),
         'updated': '',
     }
     msg = ticket.messages.last()
     if msg:
         context.update({
             'updated': admin_date('created_at')(msg),
             'updater': admin_link('author')(self, msg) if msg.author else msg.author_name,
         })
         context['updated'] = '. Updated by %(updater)s about %(updated)s' % context
     return '<h4>Added by %(creator)s about %(created)s%(updated)s</h4>' % context
示例#2
0
 def display_summary(self, ticket):
     context = {
         'creator': admin_link('creator')(self, ticket) if ticket.creator else ticket.creator_name,
         'created': admin_date('created_on')(ticket),
         'updated': '',
     }
     msg = ticket.messages.last()
     if msg:
         context.update({
             'updated': admin_date('created_on')(msg),
             'updater': admin_link('author')(self, msg) if msg.author else msg.author_name,
         })
         context['updated'] = '. Updated by %(updater)s about %(updated)s' % context
     return '<h4>Added by %(creator)s about %(created)s%(updated)s</h4>' % context
示例#3
0
class MonitorDataAdmin(ExtendedModelAdmin):
    list_display = ('id', 'monitor', content_object_link, 'display_created',
                    'value')
    list_filter = ('monitor', ResourceDataListFilter)
    add_fields = ('monitor', 'content_type', 'object_id', 'created_at',
                  'value')
    fields = ('monitor', 'content_type', content_object_link,
              'display_created', 'value', 'state')
    change_readonly_fields = fields
    list_select_related = ('content_type', )
    search_fields = ('content_object_repr', )
    date_hierarchy = 'created_at'

    display_created = admin_date('created_at', short_description=_("Created"))

    def filter_used_monitordata(self, request, queryset):
        query_string = parse_qs(request.META['QUERY_STRING'])
        resource_data = query_string.get('resource_data')
        if resource_data:
            mdata = ResourceData.objects.get(pk=int(resource_data[0]))
            resource = mdata.resource
            ids = []
            for monitor, dataset in mdata.get_monitor_datasets():
                dataset = resource.aggregation_instance.filter(dataset)
                if isinstance(dataset, MonitorData):
                    ids.append(dataset.id)
                else:
                    ids += dataset.values_list('id', flat=True)
            return queryset.filter(id__in=ids)
        return queryset

    def get_queryset(self, request):
        queryset = super(MonitorDataAdmin, self).get_queryset(request)
        queryset = self.filter_used_monitordata(request, queryset)
        return queryset.prefetch_related('content_object')
示例#4
0
class SMTPLogAdmin(admin.ModelAdmin):
    list_display = ('id', 'message_link', 'colored_result', 'date_delta',
                    'log_message')
    list_filter = ('result', )
    fields = ('message_link', 'colored_result', 'date_delta', 'log_message')
    readonly_fields = fields

    message_link = admin_link('message')
    colored_result = admin_colored('result', colors=COLORS, bold=False)
    date_delta = admin_date('date')
示例#5
0
 def content_html(self, msg):
     context = {
         'number': msg.number,
         'time': admin_date('created_on')(msg),
         'author': admin_link('author')(msg) if msg.author else msg.author_name,
     }
     summary = _("#%(number)i Updated by %(author)s about %(time)s") % context
     header = '<strong style="color:#666;">%s</strong><hr />' % summary
     content = markdown(msg.content)
     content = content.replace('>\n', '>')
     content = '<div style="padding-left:20px;">%s</div>' % content
     return header + content
示例#6
0
    def content_html(self, msg):
        context = {
            'number': msg.number,
            'time': admin_date('created_at')(msg),
            'author': admin_link('author')(msg) if msg.author else msg.author_name,
        }
        summary = _("#%(number)i Updated by %(author)s about %(time)s") % context
        header = '<strong style="color:#666;">%s</strong><hr />' % summary

        content = markdown(msg.content)
        content = content.replace('>\n', '>')
        content = '<div style="padding-left:20px;">%s</div>' % content

        return header + content
示例#7
0
class BackendLogAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
    list_display = (
        'id',
        'backend',
        'server_link',
        'display_state',
        'exit_code',
        'display_created',
        'execution_time',
    )
    list_display_links = ('id', 'backend')
    list_filter = ('state', 'server', 'backend', 'operations__action')
    search_fields = ('script', )
    date_hierarchy = 'created_at'
    inlines = (BackendOperationInline, )
    fields = ('backend', 'server_link', 'state', 'display_script',
              'mono_stdout', 'mono_stderr', 'mono_traceback', 'exit_code',
              'task_id', 'display_created', 'execution_time')
    readonly_fields = fields
    actions = (retry_backend, )
    change_view_actions = actions

    server_link = admin_link('server')
    display_created = admin_date('created_at', short_description=_("Created"))
    display_state = admin_colored('state', colors=STATE_COLORS)
    display_script = display_code('script')
    mono_stdout = display_mono('stdout')
    mono_stderr = display_mono('stderr')
    mono_traceback = display_mono('traceback')

    class Media:
        css = {'all': ('orchestra/css/pygments/github.css', )}

    def get_queryset(self, request):
        """ Order by structured name and imporve performance """
        qs = super(BackendLogAdmin, self).get_queryset(request)
        return qs.select_related('server').defer('script', 'stdout')

    def has_add_permission(self, *args, **kwargs):
        return False
示例#8
0
class LogEntryAdmin(admin.ModelAdmin):
    list_display = (
        'display_action_time',
        'user_link',
        'display_message',
    )
    list_filter = (
        'action_flag',
        ('user', admin.RelatedOnlyFieldListFilter),
        ('content_type', admin.RelatedOnlyFieldListFilter),
    )
    date_hierarchy = 'action_time'
    search_fields = ('object_repr', 'change_message', 'user__username')
    fields = ('user_link', 'content_object_link', 'display_action_time',
              'display_action', 'change_message')
    readonly_fields = (
        'user_link',
        'content_object_link',
        'display_action_time',
        'display_action',
    )
    actions = None
    list_select_related = ('user', 'content_type')
    list_display_links = None

    user_link = admin_link('user')
    display_action_time = admin_date('action_time',
                                     short_description=_("Time"))

    @mark_safe
    def display_message(self, log):
        edit = format_html(
            '<a href="{url}"><img src="{img}"></img></a>', **{
                'url': reverse('admin:admin_logentry_change', args=(log.pk, )),
                'img': static('admin/img/icon-changelink.svg'),
            })
        if log.is_addition():
            return _('Added "%(link)s". %(edit)s') % {
                'link': self.content_object_link(log),
                'edit': edit
            }
        elif log.is_change():
            return _('Changed "%(link)s" - %(changes)s %(edit)s') % {
                'link': self.content_object_link(log),
                'changes': log.get_change_message(),
                'edit': edit,
            }
        elif log.is_deletion():
            return _('Deleted "%(object)s." %(edit)s') % {
                'object': log.object_repr,
                'edit': edit,
            }

    display_message.short_description = _("Message")
    display_message.admin_order_field = 'action_flag'

    def display_action(self, log):
        if log.is_addition():
            return _("Added")
        elif log.is_change():
            return _("Changed")
        return _("Deleted")

    display_action.short_description = _("Action")
    display_action.admin_order_field = 'action_flag'

    def content_object_link(self, log):
        ct = log.content_type
        view = 'admin:%s_%s_change' % (ct.app_label, ct.model)
        try:
            url = reverse(view, args=(log.object_id, ))
        except NoReverseMatch:
            return log.object_repr
        return format_html('<a href="{}">{}</a>', url, log.object_repr)

    content_object_link.short_description = _("Content object")
    content_object_link.admin_order_field = 'object_repr'

    def render_change_form(self,
                           request,
                           context,
                           add=False,
                           change=False,
                           form_url='',
                           obj=None):
        """ Add rel_opts and object to context """
        if not add and 'edit' in request.GET.urlencode():
            context.update({
                'rel_opts': obj.content_type.model_class()._meta,
                'object': obj,
            })
        return super(LogEntryAdmin,
                     self).render_change_form(request, context, add, change,
                                              form_url, obj)

    def response_change(self, request, obj):
        """ save and continue preserve edit query string """
        response = super(LogEntryAdmin, self).response_change(request, obj)
        if 'edit' in request.GET.urlencode() and 'edit' not in response.url:
            return HttpResponseRedirect(response.url + '?edit=True')
        return response

    def response_post_save_change(self, request, obj):
        """ save redirect to object history """
        if 'edit' in request.GET.urlencode():
            opts = obj.content_type.model_class()._meta
            view = 'admin:%s_%s_history' % (opts.app_label, opts.model_name)
            post_url = reverse(view, args=(obj.object_id, ))
            preserved_filters = self.get_preserved_filters(request)
            post_url = add_preserved_filters(
                {
                    'preserved_filters': preserved_filters,
                    'opts': opts
                }, post_url)
            return HttpResponseRedirect(post_url)
        return super(LogEntryAdmin,
                     self).response_post_save_change(request, obj)

    def has_add_permission(self, *args, **kwargs):
        return False

    def has_delete_permission(self, *args, **kwargs):
        return False

    def log_addition(self, *args, **kwargs):
        pass

    def log_change(self, *args, **kwargs):
        pass

    def log_deletion(self, *args, **kwargs):
        pass
示例#9
0
class MessageAdmin(ExtendedModelAdmin):
    list_display = (
        'display_subject',
        'colored_state',
        'priority',
        'to_address',
        'from_address',
        'created_at_delta',
        'display_retries',
        'last_try_delta',
    )
    list_filter = ('state', 'priority', 'retries')
    list_prefetch_related = ('logs', )
    search_fields = (
        'to_address',
        'from_address',
        'subject',
    )
    fieldsets = (
        (None, {
            'fields':
            ('state', 'priority', ('retries', 'last_try_delta',
                                   'created_at_delta'), 'display_full_subject',
             'display_from', 'display_to', 'display_content'),
        }),
        (_("Edit"), {
            'classes': ('collapse', ),
            'fields': ('subject', 'from_address', 'to_address', 'content'),
        }),
    )
    readonly_fields = (
        'retries',
        'last_try_delta',
        'created_at_delta',
        'display_full_subject',
        'display_to',
        'display_from',
        'display_content',
    )
    date_hierarchy = 'created_at'
    change_view_actions = (last, )

    colored_state = admin_colored('state', colors=COLORS)
    created_at_delta = admin_date('created_at')
    last_try_delta = admin_date('last_try')

    def display_subject(self, instance):
        subject = instance.subject
        if len(subject) > 64:
            return mark_safe(subject[:64] + '&hellip;')
        return subject

    display_subject.short_description = _("Subject")
    display_subject.admin_order_field = 'subject'

    def display_retries(self, instance):
        num_logs = instance.logs__count
        if num_logs == 1:
            pk = instance.logs.all()[0].id
            url = reverse('admin:mailer_smtplog_change', args=(pk, ))
        else:
            url = reverse('admin:mailer_smtplog_changelist')
            url += '?&message=%i' % instance.pk
        return format_html(
            '<a href="{}" onclick="return showAddAnotherPopup(this);">{}</a>',
            url, instance.retries)

    display_retries.short_description = _("Retries")
    display_retries.admin_order_field = 'retries'

    def display_content(self, instance):
        part = email.message_from_string(instance.content)
        payload = part.get_payload()
        if isinstance(payload, list):
            for cpart in payload:
                cpayload = cpart.get_payload()
                if cpart.get_content_type().startswith('text/'):
                    part = cpart
                    payload = cpayload
                    if cpart.get_content_type() == 'text/html':
                        payload = '<div style="padding-left:110px">%s</div>' % payload
                        # prioritize HTML
                        break
        if part.get('Content-Transfer-Encoding') == 'base64':
            payload = base64.b64decode(payload)
            charset = part.get_charsets()[0]
            if charset:
                payload = payload.decode(charset)
        if part.get_content_type() == 'text/plain':
            payload = payload.replace('\n', '<br>').replace(' ', '&nbsp;')
        return mark_safe(payload)

    display_content.short_description = _("Content")

    def display_full_subject(self, instance):
        return instance.subject

    display_full_subject.short_description = _("Subject")

    def display_from(self, instance):
        return instance.from_address

    display_from.short_description = _("From")

    def display_to(self, instance):
        return instance.to_address

    display_to.short_description = _("To")

    def get_urls(self):
        from django.conf.urls import url
        urls = super().get_urls()
        info = self.model._meta.app_label, self.model._meta.model_name
        urls.insert(
            0,
            url(r'^send-pending/$',
                wrap_admin_view(self, self.send_pending_view),
                name='%s_%s_send_pending' % info))
        return urls

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.annotate(Count('logs')).defer('content')

    def send_pending_view(self, request):
        task(send_pending).apply_async()
        self.message_user(
            request, _("Pending messages are being sent on the background."))
        return redirect('..')

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'subject':
            kwargs['widget'] = forms.TextInput(attrs={'size': '100'})
        return super().formfield_for_dbfield(db_field, **kwargs)
示例#10
0
class BillAdmin(BillAdminMixin, ExtendedModelAdmin):
    list_display = ('number', 'type_link', 'account_link', 'closed_on_display',
                    'updated_on_display', 'num_lines', 'display_total',
                    'display_payment_state', 'is_sent')
    list_filter = (
        BillTypeListFilter,
        'is_open',
        'is_sent',
        TotalListFilter,
        PaymentStateListFilter,
        AmendedListFilter,
        'account__is_active',
    )
    add_fields = ('account', 'type', 'amend_of', 'is_open', 'due_on',
                  'comments')
    change_list_template = 'admin/bills/bill/change_list.html'
    fieldsets = (
        (None, {
            'fields': [
                'number', 'type', (), 'account_link',
                'display_total_with_subtotals', 'display_payment_state',
                'is_sent', 'comments'
            ],
        }),
        (_("Dates"), {
            'classes': ('collapse', ),
            'fields': ('created_on_display', 'closed_on_display',
                       'updated_on_display', 'due_on'),
        }),
        (_("Raw"), {
            'classes': ('collapse', ),
            'fields': ('html', ),
        }),
    )
    list_prefetch_related = ('transactions', 'lines__sublines')
    search_fields = ('number', 'account__username', 'comments')
    change_view_actions = [
        actions.manage_lines,
        actions.view_bill,
        actions.download_bills,
        actions.send_bills,
        actions.close_bills,
        actions.amend_bills,
        actions.close_send_download_bills,
    ]
    actions = [
        actions.manage_lines,
        actions.download_bills,
        actions.close_bills,
        actions.send_bills,
        actions.amend_bills,
        actions.bill_report,
        actions.service_report,
        actions.close_send_download_bills,
        list_accounts,
    ]
    change_readonly_fields = ('account_link', 'type', 'is_open',
                              'amend_of_link')
    readonly_fields = (
        'number',
        'display_total',
        'is_sent',
        'display_payment_state',
        'created_on_display',
        'closed_on_display',
        'updated_on_display',
        'display_total_with_subtotals',
    )
    date_hierarchy = 'closed_on'

    created_on_display = admin_date('created_on',
                                    short_description=_("Created"))
    closed_on_display = admin_date('closed_on', short_description=_("Closed"))
    updated_on_display = admin_date('updated_on',
                                    short_description=_("Updated"))
    amend_of_link = admin_link('amend_of')

    #    def amend_links(self, bill):
    #        links = []
    #        for amend in bill.amends.all():
    #            url = reverse('admin:bills_bill_change', args=(amend.id,))
    #            links.append('<a href="{url}">{num}</a>'.format(url=url, num=amend.number))
    #        return '<br>'.join(links)
    #    amend_links.short_description = _("Amends")
    #    amend_links.allow_tags = True

    def num_lines(self, bill):
        return bill.lines__count

    num_lines.admin_order_field = 'lines__count'
    num_lines.short_description = _("lines")

    def display_total(self, bill):
        currency = settings.BILLS_CURRENCY.lower()
        return '%s &%s;' % (bill.compute_total(), currency)

    display_total.allow_tags = True
    display_total.short_description = _("total")
    display_total.admin_order_field = 'approx_total'

    def type_link(self, bill):
        bill_type = bill.type.lower()
        url = reverse('admin:bills_%s_changelist' % bill_type)
        return '<a href="%s">%s</a>' % (url, bill.get_type_display())

    type_link.allow_tags = True
    type_link.short_description = _("type")
    type_link.admin_order_field = 'type'

    def get_urls(self):
        """ Hook bill lines management URLs on bill admin """
        urls = super().get_urls()
        admin_site = self.admin_site
        extra_urls = [
            url("^manage-lines/$",
                admin_site.admin_view(
                    BillLineManagerAdmin(BillLine,
                                         admin_site).changelist_view),
                name='bills_bill_manage_lines'),
        ]
        return extra_urls + urls

    def get_readonly_fields(self, request, obj=None):
        fields = super().get_readonly_fields(request, obj)
        if obj and not obj.is_open:
            fields += self.add_fields
        return fields

    def get_fieldsets(self, request, obj=None):
        fieldsets = super().get_fieldsets(request, obj)
        if obj:
            # Switches between amend_of_link and amend_links fields
            fields = fieldsets[0][1]['fields']
            if obj.amend_of_id:
                fields[2] = 'amend_of_link'
            else:
                fields[2] = ()
            if obj.is_open:
                fieldsets = fieldsets[0:-1]
        return fieldsets

    def get_change_view_actions(self, obj=None):
        actions = super().get_change_view_actions(obj)
        exclude = []
        if obj:
            if not obj.is_open:
                exclude += ['close_bills', 'close_send_download_bills']
            if obj.type not in obj.AMEND_MAP:
                exclude += ['amend_bills']
        return [action for action in actions if action.__name__ not in exclude]

    def get_inline_instances(self, request, obj=None):
        cls = type(self)
        if obj and not obj.is_open:
            if obj.amends.all():
                cls.inlines = [AmendInline, ClosedBillLineInline]
            else:
                cls.inlines = [ClosedBillLineInline]
        else:
            cls.inlines = [BillLineInline]
        return super().get_inline_instances(request, obj)

    def formfield_for_dbfield(self, db_field, **kwargs):
        """ Make value input widget bigger """
        if db_field.name == 'comments':
            kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 4})
        elif db_field.name == 'html':
            kwargs['widget'] = forms.Textarea(attrs={'cols': 150, 'rows': 20})
        formfield = super().formfield_for_dbfield(db_field, **kwargs)
        if db_field.name == 'amend_of':
            formfield.queryset = formfield.queryset.filter(is_open=False)
        return formfield

    def change_view(self, request, object_id, **kwargs):
        # TODO raise404, here and everywhere
        bill = self.get_object(request, unquote(object_id))
        actions.validate_contact(request, bill, error=False)
        return super().change_view(request, object_id, **kwargs)
示例#11
0
class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
    list_display = ('display_description', 'service_link', 'account_link',
                    'content_object_link', 'display_registered_on',
                    'display_billed_until', 'display_cancelled_on',
                    'display_metric')
    list_filter = (
        ActiveOrderListFilter,
        IgnoreOrderListFilter,
        BilledOrderListFilter,
        'account__type',
        'service',
    )
    default_changelist_filters = (('ignore', '0'), )
    actions = (BillSelectedOrders(), mark_as_ignored, mark_as_not_ignored,
               report, list_accounts)
    change_view_actions = (BillSelectedOrders(), mark_as_ignored,
                           mark_as_not_ignored)
    date_hierarchy = 'registered_on'
    inlines = (MetricStorageInline, )
    add_inlines = ()
    search_fields = (
        'account__username',
        'content_object_repr',
        'description',
    )
    list_prefetch_related = (
        'content_object',
        Prefetch('metrics', queryset=MetricStorage.objects.order_by('-id')),
    )
    list_select_related = ('account', 'service')
    add_fieldsets = (
        (None, {
            'fields': ('account', 'service')
        }),
        (_("Object"), {
            'fields': (
                'content_type',
                'object_id',
            ),
        }),
        (_("State"), {
            'fields': ('registered_on', 'cancelled_on', 'billed_on',
                       'billed_metric', 'billed_until')
        }),
        (None, {
            'fields': (
                'description',
                'ignore',
            ),
        }),
    )
    fieldsets = (
        (None, {
            'fields': ('account_link', 'service_link', 'content_object_link'),
        }),
        (_("State"), {
            'fields': ('registered_on', 'cancelled_on', 'billed_on',
                       'billed_metric', 'billed_until')
        }),
        (None, {
            'fields': ('description', 'ignore', 'bills_links'),
        }),
    )
    readonly_fields = ('content_object_repr', 'content_object_link',
                       'bills_links', 'account_link', 'service_link')

    service_link = admin_link('service')
    display_registered_on = admin_date('registered_on')
    display_cancelled_on = admin_date('cancelled_on')

    def display_description(self, order):
        return order.description[:64]

    display_description.short_description = _("Description")
    display_description.allow_tags = True
    display_description.admin_order_field = 'description'

    def content_object_link(self, order):
        if order.content_object:
            try:
                url = change_url(order.content_object)
            except NoReverseMatch:
                # Does not has admin
                return order.content_object_repr
            description = str(order.content_object)
            return '<a href="{url}">{description}</a>'.format(
                url=url, description=description)
        return order.content_object_repr

    content_object_link.short_description = _("Content object")
    content_object_link.allow_tags = True
    content_object_link.admin_order_field = 'content_object_repr'

    def bills_links(self, order):
        bills = []
        make_link = admin_link()
        for line in order.lines.select_related('bill').distinct('bill'):
            bills.append(make_link(line.bill))
        return '<br>'.join(bills)

    bills_links.short_description = _("Bills")
    bills_links.allow_tags = True

    def display_billed_until(self, order):
        billed_until = order.billed_until
        red = False
        human = escape(naturaldate(billed_until))
        if billed_until:
            if order.cancelled_on and order.cancelled_on <= billed_until:
                pass
            elif order.service.billing_period == order.service.NEVER:
                human = _("Forever")
            elif order.service.payment_style == order.service.POSTPAY:
                boundary = order.service.handler.get_billing_point(order)
                if billed_until < boundary:
                    red = True
            elif billed_until < timezone.now().date():
                red = True
        color = 'style="color:red;"' if red else ''
        return '<span title="{raw}" {color}>{human}</span>'.format(
            raw=escape(str(billed_until)),
            color=color,
            human=human,
        )

    display_billed_until.short_description = _("billed until")
    display_billed_until.allow_tags = True
    display_billed_until.admin_order_field = 'billed_until'

    def display_metric(self, order):
        """
        dispalys latest metric value, don't uses latest() because not loosing prefetch_related
        """
        try:
            metric = order.metrics.all()[0]
        except IndexError:
            return ''
        return metric.value

    display_metric.short_description = _("Metric")

    def formfield_for_dbfield(self, db_field, **kwargs):
        """ Make value input widget bigger """
        if db_field.name == 'description':
            kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
        return super().formfield_for_dbfield(db_field, **kwargs)
示例#12
0
class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
    list_display = ('id', 'bill_link', 'account_link', 'source_link',
                    'display_created_at', 'display_modified_at',
                    'display_state', 'amount', 'process_link')
    list_filter = ('source__method', 'state')
    fieldsets = (
        (None, {
            'classes': ('wide', ),
            'fields': ('account_link', 'bill_link', 'source_link',
                       'display_state', 'amount', 'currency', 'process_link')
        }),
        (_("Dates"), {
            'classes': ('wide', ),
            'fields': ('display_created_at', 'display_modified_at'),
        }),
    )
    add_fieldsets = ((None, {
        'classes': ('wide', ),
        'fields': (
            'bill',
            'source',
            'display_state',
            'amount',
            'currency',
        )
    }), )
    change_view_actions = (actions.process_transactions,
                           actions.mark_as_executed, actions.mark_as_secured,
                           actions.mark_as_rejected, actions.reissue)
    search_fields = ('bill__number', 'bill__account__username', 'id')
    actions = change_view_actions + (
        actions.report,
        list_accounts,
    )
    filter_by_account_fields = ('bill', 'source')
    readonly_fields = ('bill_link', 'display_state', 'process_link',
                       'account_link', 'source_link', 'display_created_at',
                       'display_modified_at')
    list_select_related = ('source', 'bill__account', 'process')
    date_hierarchy = 'created_at'

    bill_link = admin_link('bill')
    source_link = admin_link('source')
    process_link = admin_link('process', short_description=_("proc"))
    account_link = admin_link('bill__account')
    display_created_at = admin_date('created_at',
                                    short_description=_("Created"))
    display_modified_at = admin_date('modified_at',
                                     short_description=_("Modified"))

    def has_delete_permission(self, *args, **kwargs):
        return False

    def get_actions(self, request):
        actions = super().get_actions(request)
        if 'delete_selected' in actions:
            del actions['delete_selected']
        return actions

    def get_change_readonly_fields(self, request, obj):
        if obj.state in (Transaction.WAITTING_PROCESSING,
                         Transaction.WAITTING_EXECUTION):
            return ()
        return ('amount', 'currency')

    def get_change_view_actions(self, obj=None):
        actions = super(TransactionAdmin, self).get_change_view_actions()
        exclude = []
        if obj:
            if obj.state == Transaction.WAITTING_PROCESSING:
                exclude = ['mark_as_executed', 'mark_as_secured', 'reissue']
            elif obj.state == Transaction.WAITTING_EXECUTION:
                exclude = [
                    'process_transactions', 'mark_as_secured', 'reissue'
                ]
            if obj.state == Transaction.EXECUTED:
                exclude = [
                    'process_transactions', 'mark_as_executed', 'reissue'
                ]
            elif obj.state == Transaction.REJECTED:
                exclude = [
                    'process_transactions', 'mark_as_executed',
                    'mark_as_secured', 'mark_as_rejected'
                ]
            elif obj.state == Transaction.SECURED:
                return []
        return [action for action in actions if action.__name__ not in exclude]

    def display_state(self, obj):
        state = admin_colored('state', colors=STATE_COLORS)(obj)
        help_text = obj.get_state_help()
        state = state.replace('<span ', '<span title="%s" ' % help_text)
        return state

    display_state.admin_order_field = 'state'
    display_state.short_description = _("State")
    display_state.allow_tags = True
示例#13
0
    class ResourceInline(GenericTabularInline):
        model = ResourceData
        verbose_name_plural = _("resources")
        form = ResourceForm
        formset = ResourceInlineFormSet
        can_delete = False
        fields = (
            'verbose_name',
            'display_used',
            'display_updated',
            'allocated',
            'unit',
        )
        readonly_fields = (
            'display_used',
            'display_updated',
        )

        class Media:
            css = {'all': ('orchestra/css/hide-inline-id.css', )}

        display_updated = admin_date('updated_at', default=_("Never"))

        def get_fieldsets(self, request, obj=None):
            if obj:
                opts = self.parent_model._meta
                url = reverse('admin:resources_resourcedata_list_related',
                              args=(opts.app_label, opts.model_name, obj.id))
                link = '<a href="%s">%s</a>' % (url, _("List related"))
                self.verbose_name_plural = mark_safe(
                    _("Resources") + ' ' + link)
            return super(ResourceInline, self).get_fieldsets(request, obj)

        @mark_safe
        def display_used(self, rdata):
            update = ''
            history = ''
            if rdata.pk:
                context = {
                    'title':
                    _("Update"),
                    'url':
                    reverse('admin:resources_resourcedata_monitor',
                            args=(rdata.pk, )),
                    'image':
                    '<img src="%s"></img>' %
                    static('orchestra/images/reload.png'),
                }
                update = '<a href="%(url)s" title="%(title)s">%(image)s</a>' % context
                context.update({
                    'title':
                    _("Show history"),
                    'image':
                    '<img src="%s"></img>' %
                    static('orchestra/images/history.png'),
                    'url':
                    reverse('admin:resources_resourcedata_show_history',
                            args=(rdata.pk, )),
                    'popup':
                    'onclick="return showAddAnotherPopup(this);"',
                })
                history = '<a href="%(url)s" title="%(title)s" %(popup)s>%(image)s</a>' % context
            if rdata.used is not None:
                used_url = reverse(
                    'admin:resources_resourcedata_used_monitordata',
                    args=(rdata.pk, ))
                used = '<a href="%s">%s %s</a>' % (used_url, rdata.used,
                                                   rdata.unit)
                return ' '.join(map(str, (used, update, history)))
            if rdata.resource.monitors:
                return _("Unknonw %s %s") % (update, history)
            return _("No monitor")

        display_used.short_description = _("Used")

        def has_add_permission(self, *args, **kwargs):
            """ Hidde add another """
            return False
示例#14
0
class ResourceDataAdmin(ExtendedModelAdmin):
    list_display = ('id', 'resource_link', content_object_link, 'allocated',
                    'display_used', 'display_updated')
    list_filter = ('resource', )
    fields = (
        'resource_link',
        'content_type',
        content_object_link,
        'display_updated',
        'display_used',
        'allocated',
    )
    search_fields = ('content_object_repr', )
    readonly_fields = fields
    actions = (run_monitor, show_history)
    change_view_actions = actions
    ordering = ('-updated_at', )
    list_select_related = ('resource__content_type', 'content_type')

    resource_link = admin_link('resource')
    display_updated = admin_date('updated_at', short_description=_("Updated"))

    def get_urls(self):
        """Returns the additional urls for the change view links"""
        urls = super(ResourceDataAdmin, self).get_urls()
        admin_site = self.admin_site
        opts = self.model._meta
        return [
            url('^(\d+)/used-monitordata/$',
                admin_site.admin_view(self.used_monitordata_view),
                name='%s_%s_used_monitordata' %
                (opts.app_label, opts.model_name)),
            url('^history_data/$',
                admin_site.admin_view(history_data),
                name='%s_%s_history_data' % (opts.app_label, opts.model_name)),
            url('^list-related/(.+)/(.+)/(\d+)/$',
                admin_site.admin_view(self.list_related_view),
                name='%s_%s_list_related' % (opts.app_label, opts.model_name)),
        ] + urls

    def display_used(self, rdata):
        if rdata.used is None:
            return ''
        url = reverse('admin:resources_resourcedata_used_monitordata',
                      args=(rdata.pk, ))
        return format_html('<a href="{}">{} {}</a>', url, rdata.used,
                           rdata.unit)

    display_used.short_description = _("Used")
    display_used.admin_order_field = 'used'

    def has_add_permission(self, *args, **kwargs):
        return False

    def used_monitordata_view(self, request, object_id):
        url = reverse('admin:resources_monitordata_changelist')
        url += '?resource_data=%s' % object_id
        return redirect(url)

    def list_related_view(self, request, app_name, model_name, object_id):
        resources = Resource.objects.select_related('content_type')
        resource_models = {
            r.content_type.model_class(): r.content_type_id
            for r in resources
        }
        # Self
        model = apps.get_model(app_name, model_name)
        obj = model.objects.get(id=int(object_id))
        ct_id = resource_models[model]
        qset = Q(content_type_id=ct_id,
                 object_id=obj.id,
                 resource__is_active=True)
        # Related
        for field, rel in obj._meta.fields_map.items():
            try:
                ct_id = resource_models[rel.related_model]
            except KeyError:
                pass
            else:
                manager = getattr(obj, field)
                ids = manager.values_list('id', flat=True)
                qset = Q(qset) | Q(content_type_id=ct_id,
                                   object_id__in=ids,
                                   resource__is_active=True)
        related = ResourceData.objects.filter(qset)
        related_ids = related.values_list('id', flat=True)
        related_ids = ','.join(map(str, related_ids))
        url = reverse('admin:resources_resourcedata_changelist')
        url += '?id__in=%s' % related_ids
        return redirect(url)
示例#15
0
class TicketAdmin(ExtendedModelAdmin):
    list_display = (
        'unbold_id', 'bold_subject', 'display_creator', 'display_owner',
        'display_queue', 'display_priority', 'display_state', 'updated'
    )
    list_display_links = ('unbold_id', 'bold_subject')
    list_filter = (
        MyTicketsListFilter, 'queue', 'priority', TicketStateListFilter,
    )
    default_changelist_filters = (
        ('state', 'OPEN'),
    )
    date_hierarchy = 'created_at'
    search_fields = (
        'id', 'subject', 'creator__username', 'creator__email', 'queue__name',
        'owner__username'
    )
    actions = (
        mark_as_unread, mark_as_read, 'delete_selected', reject_tickets,
        resolve_tickets, close_tickets, take_tickets
    )
    sudo_actions = ('delete_selected',)
    change_view_actions = (
        resolve_tickets, close_tickets, reject_tickets, take_tickets
    )
#    change_form_template = "admin/orchestra/change_form.html"
    form = TicketForm
    add_inlines = ()
    inlines = (MessageReadOnlyInline, MessageInline)
    readonly_fields = (
        'display_summary', 'display_queue', 'display_owner', 'display_state',
        'display_priority'
    )
    readonly_fieldsets = (
        (None, {
            'fields': ('display_summary',
                       ('display_queue', 'display_owner'),
                       ('display_state', 'display_priority'),
                       'display_description')
        }),
    )
    fieldsets = readonly_fieldsets + (
        ('Update', {
            'classes': ('collapse',),
            'fields': ('subject',
                      ('queue', 'owner',),
                      ('state', 'priority'),
                       'description')
        }),
    )
    add_fieldsets = (
        (None, {
            'fields': ('subject',
                      ('queue', 'owner',),
                      ('state', 'priority'),
                      'description')
        }),
    )
    list_select_related = ('queue', 'owner', 'creator')

    class Media:
        css = {
            'all': ('issues/css/ticket-admin.css',)
        }
        js = (
            'issues/js/ticket-admin.js',
        )

    display_creator = admin_link('creator')
    display_queue = admin_link('queue')
    display_owner = admin_link('owner')
    updated = admin_date('updated_at')
    display_state = admin_colored('state', colors=STATE_COLORS, bold=False)
    display_priority = admin_colored('priority', colors=PRIORITY_COLORS, bold=False)

    @mark_safe
    def display_summary(self, ticket):
        context = {
            'creator': admin_link('creator')(self, ticket) if ticket.creator else ticket.creator_name,
            'created': admin_date('created_at')(ticket),
            'updated': '',
        }
        msg = ticket.messages.last()
        if msg:
            context.update({
                'updated': admin_date('created_at')(msg),
                'updater': admin_link('author')(self, msg) if msg.author else msg.author_name,
            })
            context['updated'] = '. Updated by %(updater)s about %(updated)s' % context
        return '<h4>Added by %(creator)s about %(created)s%(updated)s</h4>' % context
    display_summary.short_description = 'Summary'

    def unbold_id(self, ticket):
        """ Unbold id if ticket is read """
        if ticket.is_read_by(self.user):
            return format_html('<span style="font-weight:normal;font-size:11px;">{}</span>', ticket.pk)
        return ticket.pk
    unbold_id.short_description = "#"
    unbold_id.admin_order_field = 'id'

    def bold_subject(self, ticket):
        """ Bold subject when tickets are unread for request.user """
        if ticket.is_read_by(self.user):
            return ticket.subject
        return format_html("<strong class='unread'>{}</strong>", ticket.subject)
    bold_subject.short_description = _("Subject")
    bold_subject.admin_order_field = 'subject'

    def formfield_for_dbfield(self, db_field, **kwargs):
        """ Make value input widget bigger """
        if db_field.name == 'subject':
            kwargs['widget'] = forms.TextInput(attrs={'size':'120'})
        return super(TicketAdmin, self).formfield_for_dbfield(db_field, **kwargs)

    def save_model(self, request, obj, *args, **kwargs):
        """ Define creator for new tickets """
        if not obj.pk:
            obj.creator = request.user
        super(TicketAdmin, self).save_model(request, obj, *args, **kwargs)
        obj.mark_as_read_by(request.user)

    def get_urls(self):
        """ add markdown preview url """
        return [
            url(r'^preview/$',
                wrap_admin_view(self, self.message_preview_view))
        ] + super(TicketAdmin, self).get_urls()

    def add_view(self, request, form_url='', extra_context=None):
        """ Do not sow message inlines """
        return super(TicketAdmin, self).add_view(request, form_url, extra_context)

    def change_view(self, request, object_id, form_url='', extra_context=None):
        """ Change view actions based on ticket state """
        ticket = get_object_or_404(Ticket, pk=object_id)
        # Change view actions based on ticket state
        self.change_view_actions = filter_actions(self, ticket, request)
        if request.method == 'POST':
            # Hack: Include the ticket changes on the request.POST
            #       other approaches get really messy
            changes = get_ticket_changes(self, request, ticket)
            if changes:
                content = markdown_formated_changes(changes)
                content += request.POST['messages-2-0-content']
                request.POST['messages-2-0-content'] = content
        ticket.mark_as_read_by(request.user)
        context = {'title': "Issue #%i - %s" % (ticket.id, ticket.subject)}
        context.update(extra_context or {})
        return super(TicketAdmin, self).change_view(request, object_id, form_url=form_url,
            extra_context=context)

    def changelist_view(self, request, extra_context=None):
        # Hook user for bold_subject
        self.user = request.user
        return super(TicketAdmin,self).changelist_view(request, extra_context=extra_context)

    def message_preview_view(self, request):
        """ markdown preview render via ajax """
        data = request.POST.get("data")
        data_formated = markdown(strip_tags(data))
        return HttpResponse(data_formated)
示例#16
0
from django.utils.translation import ugettext_lazy as _
from djcelery.admin import PeriodicTaskAdmin

from orchestra.admin.utils import admin_date


display_last_run_at = admin_date('last_run_at', short_description=_("Last run"))


PeriodicTaskAdmin.list_display = ('__unicode__', display_last_run_at, 'total_run_count', 'enabled')
示例#17
0
class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
    list_display = (
        'id',
        'file_url',
        'display_transactions',
        'display_state',
        'display_created_at',
    )
    list_filter = ('state', )
    fields = ('data', 'file_url', 'created_at')
    search_fields = ('transactions__bill__number',
                     'transactions__bill__account__username', 'id')
    readonly_fields = ('data', 'file_url', 'display_transactions',
                       'created_at')
    list_prefetch_related = ('transactions', )
    inlines = [TransactionInline]
    change_view_actions = (actions.mark_process_as_executed, actions.abort,
                           actions.commit, actions.report)
    actions = change_view_actions + (actions.delete_selected, )

    display_state = admin_colored('state', colors=PROCESS_STATE_COLORS)
    display_created_at = admin_date('created_at',
                                    short_description=_("Created"))

    def file_url(self, process):
        if process.file:
            return '<a href="%s">%s</a>' % (process.file.url,
                                            process.file.name)

    file_url.allow_tags = True
    file_url.admin_order_field = 'file'

    def display_transactions(self, process):
        ids = []
        lines = []
        counter = 0
        for trans in process.transactions.all():
            color = STATE_COLORS.get(trans.state, 'black')
            state = trans.get_state_display()
            ids.append('<span style="color:%s" title="%s">%i</span>' %
                       (color, state, trans.id))
            counter += 1 + len(str(trans.id))
            if counter > 100:
                counter = 0
                lines.append(','.join(ids))
                ids = []
        lines.append(','.join(ids))
        transactions = '<br>'.join(lines)
        url = reverse('admin:payments_transaction_changelist')
        url += '?process_id=%i' % process.id
        return '<a href="%s">%s</a>' % (url, transactions)

    display_transactions.short_description = _("Transactions")
    display_transactions.allow_tags = True

    def has_add_permission(self, *args, **kwargs):
        return False

    def get_change_view_actions(self, obj=None):
        actions = super().get_change_view_actions()
        exclude = []
        if obj:
            if obj.state == TransactionProcess.EXECUTED:
                exclude.append('mark_process_as_executed')
            elif obj.state == TransactionProcess.COMMITED:
                exclude = ['mark_process_as_executed', 'abort', 'commit']
            elif obj.state == TransactionProcess.ABORTED:
                exclude = ['mark_process_as_executed', 'abort', 'commit']
        return [action for action in actions if action.__name__ not in exclude]

    def delete_view(self, request, object_id, extra_context=None):
        queryset = self.model.objects.filter(id=object_id)
        related_transactions = helpers.pre_delete_processes(
            self, request, queryset)
        response = super().delete_view(request, object_id, extra_context)
        if isinstance(response, HttpResponseRedirect):
            helpers.post_delete_processes(self, request, related_transactions)
        return response