Added resource history and domain record massive edditing
This commit is contained in:
parent
63c9f381bc
commit
0d9058d266
7
TODO.md
7
TODO.md
|
@ -423,3 +423,10 @@ Colaesce('total', 'computed_total')
|
|||
Case
|
||||
|
||||
# case on payment transaction state ? case when trans.amount >
|
||||
|
||||
# bill changelist: dates: (closed_on, created_on, updated_on)
|
||||
|
||||
|
||||
# Add record modeladmin action: select domains + add records (formset) to selected domains
|
||||
|
||||
# Resource data inline show info: link to monitor data, and history chart: link to monitor data of each item
|
||||
|
|
|
@ -47,7 +47,8 @@ class AdminFormSet(BaseModelFormSet):
|
|||
|
||||
|
||||
def adminmodelformset_factory(modeladmin, form, formset=AdminFormSet, **kwargs):
|
||||
formset = modelformset_factory(modeladmin.model, form=form, formset=formset, **kwargs)
|
||||
model = kwargs.pop('model', modeladmin.model)
|
||||
formset = modelformset_factory(model, form=form, formset=formset, **kwargs)
|
||||
formset.modeladmin = modeladmin
|
||||
return formset
|
||||
|
||||
|
|
|
@ -200,10 +200,6 @@ class Bill(models.Model):
|
|||
errors['amend_of'] = _("Related invoice is an amendment.")
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
elif self.type in self.AMEND_MAP.values():
|
||||
raise ValidationError({
|
||||
'amend_of': _("Type %s requires an amend of link.") % self.get_type_display()
|
||||
})
|
||||
|
||||
def get_payment_state_display(self):
|
||||
value = self.payment_state
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
import copy
|
||||
|
||||
from django.contrib.admin import helpers
|
||||
from django.shortcuts import render
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.admin.forms import adminmodelformset_factory
|
||||
from orchestra.admin.utils import get_object_from_url, change_url
|
||||
from orchestra.utils.python import AttrDict
|
||||
|
||||
from .forms import RecordForm, RecordEditFormSet
|
||||
from .models import Record
|
||||
|
||||
|
||||
def view_zone(modeladmin, request, queryset):
|
||||
|
@ -12,3 +24,68 @@ def view_zone(modeladmin, request, queryset):
|
|||
return TemplateResponse(request, 'admin/domains/domain/view_zone.html', context)
|
||||
view_zone.url_name = 'view-zone'
|
||||
view_zone.verbose_name = _("View zone")
|
||||
|
||||
|
||||
def edit_records(modeladmin, request, queryset):
|
||||
formsets = []
|
||||
for domain in queryset.prefetch_related('records'):
|
||||
modeladmin_copy = copy.copy(modeladmin)
|
||||
modeladmin_copy.model = Record
|
||||
link = '<a href="%s">%s</a>' % (change_url(domain), domain.name)
|
||||
modeladmin_copy.verbose_name_plural = mark_safe(link)
|
||||
RecordFormSet = adminmodelformset_factory(
|
||||
modeladmin_copy, RecordForm, formset=RecordEditFormSet, extra=1, can_delete=True)
|
||||
formset = RecordFormSet(queryset=domain.records.all(), prefix=domain.id)
|
||||
formset.instance = domain
|
||||
formset.cls = RecordFormSet
|
||||
formsets.append(formset)
|
||||
|
||||
if request.POST.get('post') == 'generic_confirmation':
|
||||
posted_formsets = []
|
||||
all_valid = True
|
||||
for formset in formsets:
|
||||
instance = formset.instance
|
||||
formset = formset.cls(
|
||||
request.POST, request.FILES, queryset=formset.queryset, prefix=instance.id)
|
||||
formset.instance = instance
|
||||
if not formset.is_valid():
|
||||
all_valid = False
|
||||
posted_formsets.append(formset)
|
||||
formsets = posted_formsets
|
||||
if all_valid:
|
||||
for formset in formsets:
|
||||
for form in formset.forms:
|
||||
form.instance.domain_id = formset.instance.id
|
||||
formset.save()
|
||||
fake_form = AttrDict({
|
||||
'changed_data': False
|
||||
})
|
||||
change_message = modeladmin.construct_change_message(request, fake_form, [formset])
|
||||
modeladmin.log_change(request, formset.instance, change_message)
|
||||
num = len(formsets)
|
||||
message = ungettext(
|
||||
_("Records for one selected domain have been updated."),
|
||||
_("Records for %i selected domains have been updated.") % num,
|
||||
num)
|
||||
modeladmin.message_user(request, message)
|
||||
return
|
||||
|
||||
opts = modeladmin.model._meta
|
||||
context = {
|
||||
'title': _("Edit records"),
|
||||
'action_name': 'Edit records',
|
||||
'action_value': 'edit_records',
|
||||
'display_objects': [],
|
||||
'queryset': queryset,
|
||||
'opts': opts,
|
||||
'app_label': opts.app_label,
|
||||
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
|
||||
'formsets': formsets,
|
||||
'obj': get_object_from_url(modeladmin, request),
|
||||
}
|
||||
return render(request, 'admin/domains/domain/edit_records.html', context)
|
||||
|
||||
|
||||
def add_records(modeladmin, request, queryset):
|
||||
# TODO
|
||||
pass
|
||||
|
|
|
@ -8,24 +8,17 @@ from orchestra.admin.utils import admin_link, change_url
|
|||
from orchestra.contrib.accounts.admin import AccountAdminMixin
|
||||
from orchestra.utils import apps
|
||||
|
||||
from .actions import view_zone
|
||||
from .actions import view_zone, edit_records
|
||||
from .filters import TopDomainListFilter
|
||||
from .forms import RecordInlineFormSet, BatchDomainCreationAdminForm
|
||||
from .forms import RecordForm, RecordInlineFormSet, BatchDomainCreationAdminForm
|
||||
from .models import Domain, Record
|
||||
|
||||
|
||||
class RecordInline(admin.TabularInline):
|
||||
model = Record
|
||||
form = RecordForm
|
||||
formset = RecordInlineFormSet
|
||||
verbose_name_plural = _("Extra records")
|
||||
|
||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||
""" Make value input widget bigger """
|
||||
if db_field.name == 'value':
|
||||
kwargs['widget'] = forms.TextInput(attrs={'size':'100'})
|
||||
if db_field.name == 'ttl':
|
||||
kwargs['widget'] = forms.TextInput(attrs={'size':'10'})
|
||||
return super(RecordInline, self).formfield_for_dbfield(db_field, **kwargs)
|
||||
|
||||
|
||||
class DomainInline(admin.TabularInline):
|
||||
|
@ -63,6 +56,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
|||
change_readonly_fields = ('name', 'serial')
|
||||
search_fields = ('name', 'account__username')
|
||||
add_form = BatchDomainCreationAdminForm
|
||||
actions = (edit_records,)
|
||||
change_view_actions = [view_zone]
|
||||
|
||||
def structured_name(self, domain):
|
||||
|
|
|
@ -2,6 +2,8 @@ from django import forms
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.admin.forms import AdminFormSet
|
||||
|
||||
from . import validators
|
||||
from .helpers import domain_for_validation
|
||||
from .models import Domain
|
||||
|
@ -63,17 +65,35 @@ class BatchDomainCreationAdminForm(forms.ModelForm):
|
|||
return cleaned_data
|
||||
|
||||
|
||||
class RecordInlineFormSet(forms.models.BaseInlineFormSet):
|
||||
class RecordForm(forms.ModelForm):
|
||||
class Meta:
|
||||
fields = ('ttl', 'type', 'value')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(RecordForm, self).__init__(*args, **kwargs)
|
||||
self.fields['ttl'].widget = forms.TextInput(attrs={'size':'10'})
|
||||
self.fields['value'].widget = forms.TextInput(attrs={'size':'100'})
|
||||
|
||||
|
||||
class ValidateZoneMixin(object):
|
||||
def clean(self):
|
||||
""" Checks if everything is consistent """
|
||||
super(RecordInlineFormSet, self).clean()
|
||||
if any(self.errors):
|
||||
super(ValidateZoneMixin, self).clean()
|
||||
if any(formset.errors):
|
||||
return
|
||||
if self.instance.name:
|
||||
if formset.instance.name:
|
||||
records = []
|
||||
for form in self.forms:
|
||||
for form in formset.forms:
|
||||
data = form.cleaned_data
|
||||
if data and not data['DELETE']:
|
||||
records.append(data)
|
||||
domain = domain_for_validation(self.instance, records)
|
||||
domain = domain_for_validation(formset.instance, records)
|
||||
validators.validate_zone(domain.render_zone())
|
||||
|
||||
|
||||
class RecordEditFormSet(ValidateZoneMixin, AdminFormSet):
|
||||
pass
|
||||
|
||||
|
||||
class RecordInlineFormSet(ValidateZoneMixin, forms.models.BaseInlineFormSet):
|
||||
pass
|
||||
|
|
|
@ -20,7 +20,7 @@ class Domain(models.Model):
|
|||
top = models.ForeignKey('domains.Domain', null=True, related_name='subdomain_set',
|
||||
editable=False)
|
||||
serial = models.IntegerField(_("serial"), default=utils.generate_zone_serial, editable=False,
|
||||
help_text=_("A revision number that changes whenever you update your domain."))
|
||||
help_text=_("A revision number that changes whenever this domain is updated."))
|
||||
refresh = models.IntegerField(_("refresh"), null=True, blank=True,
|
||||
validators=[validators.validate_zone_interval],
|
||||
help_text=_("The time a secondary DNS server waits before querying the primary DNS "
|
||||
|
@ -182,10 +182,10 @@ class Domain(models.Model):
|
|||
"%s." % settings.DOMAINS_DEFAULT_NAME_SERVER,
|
||||
utils.format_hostmaster(settings.DOMAINS_DEFAULT_HOSTMASTER),
|
||||
str(self.serial),
|
||||
settings.DOMAINS_DEFAULT_REFRESH if self.refresh is None else self.refresh,
|
||||
settings.DOMAINS_DEFAULT_RETRY if self.retry is None else self.retry,
|
||||
settings.DOMAINS_DEFAULT_EXPIRE if self.expire is None else self.expire,
|
||||
settings.DOMAINS_DEFAULT_MIN_TTL if self.min_ttl is None else self.min_ttl,
|
||||
self.refresh or settings.DOMAINS_DEFAULT_REFRESH,
|
||||
self.retry or settings.DOMAINS_DEFAULT_RETRY,
|
||||
self.expire or settings.DOMAINS_DEFAULT_EXPIRE,
|
||||
self.min_ttl or settings.DOMAINS_DEFAULT_MIN_TTL,
|
||||
]
|
||||
records.insert(0, AttrDict(
|
||||
type=Record.SOA,
|
||||
|
@ -272,13 +272,24 @@ class Record(models.Model):
|
|||
(SOA, "SOA"),
|
||||
)
|
||||
|
||||
VALIDATORS = {
|
||||
MX: validators.validate_mx_record,
|
||||
NS: validators.validate_zone_label,
|
||||
A: validate_ipv4_address,
|
||||
AAAA: validate_ipv6_address,
|
||||
CNAME: validators.validate_zone_label,
|
||||
TXT: validate_ascii,
|
||||
SRV: validators.validate_srv_record,
|
||||
SOA: validators.validate_soa_record,
|
||||
}
|
||||
|
||||
domain = models.ForeignKey(Domain, verbose_name=_("domain"), related_name='records')
|
||||
ttl = models.CharField(_("TTL"), max_length=8, blank=True,
|
||||
help_text=_("Record TTL, defaults to %s") % settings.DOMAINS_DEFAULT_TTL,
|
||||
validators=[validators.validate_zone_interval])
|
||||
type = models.CharField(_("type"), max_length=32, choices=TYPE_CHOICES)
|
||||
value = models.CharField(_("value"), max_length=256, help_text=_("MX, NS and CNAME records "
|
||||
"sould end with a dot."))
|
||||
value = models.CharField(_("value"), max_length=256,
|
||||
help_text=_("MX, NS and CNAME records sould end with a dot."))
|
||||
|
||||
def __str__(self):
|
||||
return "%s %s IN %s %s" % (self.domain, self.get_ttl(), self.type, self.value)
|
||||
|
@ -288,20 +299,13 @@ class Record(models.Model):
|
|||
# validate value
|
||||
if self.type != self.TXT:
|
||||
self.value = self.value.lower().strip()
|
||||
choices = {
|
||||
self.MX: validators.validate_mx_record,
|
||||
self.NS: validators.validate_zone_label,
|
||||
self.A: validate_ipv4_address,
|
||||
self.AAAA: validate_ipv6_address,
|
||||
self.CNAME: validators.validate_zone_label,
|
||||
self.TXT: validate_ascii,
|
||||
self.SRV: validators.validate_srv_record,
|
||||
self.SOA: validators.validate_soa_record,
|
||||
}
|
||||
try:
|
||||
choices[self.type](self.value)
|
||||
except ValidationError as error:
|
||||
raise ValidationError({'value': error})
|
||||
if self.type:
|
||||
try:
|
||||
self.VALIDATORS[self.type](self.value)
|
||||
except ValidationError as error:
|
||||
raise ValidationError({
|
||||
'value': error,
|
||||
})
|
||||
|
||||
def get_ttl(self):
|
||||
return self.ttl or settings.DOMAINS_DEFAULT_TTL
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
{% extends "admin/orchestra/generic_confirmation.html" %}
|
||||
{% load static %}
|
||||
|
||||
|
||||
{% block extrahead %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript" src="{% static 'admin/js/core.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'admin/js/admin/RelatedObjectLookups.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'admin/js/jquery.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'admin/js/actions.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'admin/js/collapse.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'admin/js/inlines.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block formset %}
|
||||
{% for formset in formsets %}
|
||||
{{ formset.as_admin }}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
|
@ -1,5 +1,6 @@
|
|||
from threading import local
|
||||
|
||||
from django.contrib.admin.models import LogEntry
|
||||
from django.core.urlresolvers import resolve
|
||||
from django.db import transaction
|
||||
from django.db.models.signals import pre_delete, post_save, m2m_changed
|
||||
|
@ -15,14 +16,14 @@ from .models import BackendLog
|
|||
|
||||
@receiver(post_save, dispatch_uid='orchestration.post_save_collector')
|
||||
def post_save_collector(sender, *args, **kwargs):
|
||||
if sender not in [BackendLog, Operation]:
|
||||
if sender not in (BackendLog, Operation, LogEntry):
|
||||
instance = kwargs.get('instance')
|
||||
OperationsMiddleware.collect(Operation.SAVE, **kwargs)
|
||||
|
||||
|
||||
@receiver(pre_delete, dispatch_uid='orchestration.pre_delete_collector')
|
||||
def pre_delete_collector(sender, *args, **kwargs):
|
||||
if sender not in [BackendLog, Operation]:
|
||||
if sender not in (BackendLog, Operation, LogEntry):
|
||||
OperationsMiddleware.collect(Operation.DELETE, **kwargs)
|
||||
|
||||
|
||||
|
|
|
@ -62,5 +62,5 @@ def history(modeladmin, request, queryset):
|
|||
context = {
|
||||
'resources': resources,
|
||||
}
|
||||
return render(request, 'admin/resources/resourcedata/report.html', context)
|
||||
return render(request, 'admin/resources/resourcedata/history.html', context)
|
||||
history.url_name = 'history'
|
||||
|
|
|
@ -254,16 +254,25 @@ def resource_inline_factory(resources):
|
|||
display_updated = admin_date('updated_at', default=_("Never"))
|
||||
|
||||
def display_used(self, data):
|
||||
from django.templatetags.static import static
|
||||
update_link = ''
|
||||
history_link = ''
|
||||
if data.pk:
|
||||
update_url = reverse('admin:resources_resourcedata_monitor', args=(data.pk,))
|
||||
update_link = '<a href="%s"><strong>%s</strong></a>' % (update_url, _("Update"))
|
||||
history_url = reverse('admin:resources_resourcedata_history', args=(data.pk,))
|
||||
popup = 'onclick="return showAddAnotherPopup(this);"'
|
||||
history_link = '<a href="%s" %s>%s</a>' % (history_url, popup, _("History"))
|
||||
context = {
|
||||
'title': _("Update"),
|
||||
'url': reverse('admin:resources_resourcedata_monitor', args=(data.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_history', args=(data.pk,)),
|
||||
'popup': 'onclick="return showAddAnotherPopup(this);"',
|
||||
})
|
||||
history = '<a href="%(url)s" title="%(title)s" %(popup)s>%(image)s</a>' % context
|
||||
if data.used is not None:
|
||||
return ' '.join(map(str, (data.used, data.resource.unit, update_link, history_link)))
|
||||
return ' '.join(map(str, (data.used, data.resource.unit, update, history)))
|
||||
return _("Unknonw %s") % update_link
|
||||
display_used.short_description = _("Used")
|
||||
display_used.allow_tags = True
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<html>
|
||||
<head>
|
||||
<title>Transaction Report</title>
|
||||
<title>Resource history</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<script src="/static/orchestra/js/Chart.min.js"></script>
|
||||
<style type="text/css">
|
||||
|
@ -64,7 +64,7 @@
|
|||
}
|
||||
new Chart(income).Bar(barData, options);
|
||||
</script>
|
||||
|
||||
|
||||
<table id="summary">
|
||||
<tr class="header">
|
||||
<th class="title column-name">{% trans "Date" %}</th>
|
BIN
orchestra/static/orchestra/images/history.png
Normal file
BIN
orchestra/static/orchestra/images/history.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
358
orchestra/static/orchestra/images/history.svg
Normal file
358
orchestra/static/orchestra/images/history.svg
Normal file
|
@ -0,0 +1,358 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:export-ydpi="90.000000"
|
||||
inkscape:export-xdpi="90.000000"
|
||||
inkscape:export-filename="/home/glic3/orchestra/django-orchestra/orchestra/static/orchestra/images/history.png"
|
||||
width="16"
|
||||
height="16"
|
||||
id="svg11300"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.91 r"
|
||||
sodipodi:docname="history.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs3">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5204">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5206" />
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5208" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5196">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5198" />
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5200" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient12512">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop12513" />
|
||||
<stop
|
||||
style="stop-color:#fff520;stop-opacity:0.89108908;"
|
||||
offset="0.50000000"
|
||||
id="stop12517" />
|
||||
<stop
|
||||
style="stop-color:#fff300;stop-opacity:0.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop12514" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12512"
|
||||
id="radialGradient278"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="55"
|
||||
cy="125"
|
||||
fx="55"
|
||||
fy="125"
|
||||
r="14.375" />
|
||||
<linearGradient
|
||||
id="linearGradient10653">
|
||||
<stop
|
||||
style="stop-color:#f3f4ff;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop10655" />
|
||||
<stop
|
||||
style="stop-color:#9193af;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop10657" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient42174">
|
||||
<stop
|
||||
style="stop-color:#a0a0a0;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop42176" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop42178" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2145">
|
||||
<stop
|
||||
style="stop-color:#fffffd;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop2147" />
|
||||
<stop
|
||||
style="stop-color:#cbcbc9;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop2149" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient37935">
|
||||
<stop
|
||||
id="stop37937"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#9497b3;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop37939"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#4c4059;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2152">
|
||||
<stop
|
||||
id="stop2154"
|
||||
offset="0.0000000"
|
||||
style="stop-color:#9aa29a;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
id="stop2156"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#b5beb5;stop-opacity:1.0000000;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2152"
|
||||
id="linearGradient4307"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.1323593,0,0,0.35150265,-12.192171,24.700536)"
|
||||
x1="8.9156475"
|
||||
y1="37.197018"
|
||||
x2="9.8855038"
|
||||
y2="52.090679" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient10653"
|
||||
id="radialGradient4309"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="11.3292"
|
||||
cy="10.58397"
|
||||
fx="11.3292"
|
||||
fy="10.58397"
|
||||
r="15.532059"
|
||||
gradientTransform="matrix(0.49213503,0,0,0.49213503,0.00830489,31.624507)" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2145"
|
||||
id="radialGradient4311"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="11.901996"
|
||||
cy="10.045444"
|
||||
fx="11.901996"
|
||||
fy="10.045444"
|
||||
r="29.292715"
|
||||
gradientTransform="matrix(0.42187886,0,0,0.42187886,1.1156771,32.810317)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient42174"
|
||||
id="linearGradient4313"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="6.342216"
|
||||
y1="7.7893324"
|
||||
x2="22.218424"
|
||||
y2="25.884274"
|
||||
gradientTransform="matrix(0.42187886,0,0,0.42187886,1.1156771,32.810317)" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5196"
|
||||
id="radialGradient5202"
|
||||
cx="23.375"
|
||||
cy="10.972863"
|
||||
fx="23.375"
|
||||
fy="10.972863"
|
||||
r="3.3478093"
|
||||
gradientTransform="matrix(2.3292353,0,0,2.4008659,-46.253114,13.661846)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5204"
|
||||
id="linearGradient5210"
|
||||
x1="19.667364"
|
||||
y1="4.2570662"
|
||||
x2="20.329933"
|
||||
y2="5.2845874"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.64158826,0,0,0.64158826,-6.8043677,32.387358)" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient37935"
|
||||
id="radialGradient5212"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="8.7468252"
|
||||
cy="6.8283234"
|
||||
fx="8.7468252"
|
||||
fy="6.8283234"
|
||||
r="29.889715"
|
||||
gradientTransform="matrix(0.51891397,0,0,0.51891397,-0.4268392,31.2037)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
stroke="#c4a000"
|
||||
fill="#babdb6"
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="0.25490196"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="22.627416"
|
||||
inkscape:cx="2.7636966"
|
||||
inkscape:cy="11.830339"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1024"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source>http://jimmac.musichall.cz</dc:source>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
|
||||
<dc:title>New Appointment</dc:title>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>appointment</rdf:li>
|
||||
<rdf:li>new</rdf:li>
|
||||
<rdf:li>meeting</rdf:li>
|
||||
<rdf:li>rvsp</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
transform="translate(0,-32)">
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path14341"
|
||||
d="m 6.1045434,32.312322 -5.20565338,6.051009 0.45627258,0.45064 4.7493808,-6.501649 z"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient4307);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path18921"
|
||||
d="M 6.0608909,32.279726 1.4186351,38.717102 2.081818,39.302631 6.0608909,32.279726 Z"
|
||||
style="fill:#fefefe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<circle
|
||||
id="path27786"
|
||||
style="fill:url(#radialGradient5212);fill-opacity:1;fill-rule:evenodd;stroke:#605773;stroke-width:0.36248955;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
|
||||
cx="8.0055094"
|
||||
cy="39.978912"
|
||||
r="7.7373796" />
|
||||
<circle
|
||||
id="path35549"
|
||||
style="fill:url(#radialGradient4311);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4313);stroke-width:0.30012295;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
|
||||
cx="7.9712114"
|
||||
cy="39.944607"
|
||||
r="6.2905145" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5202);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5210);stroke-width:0.36248916;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||
id="path4120"
|
||||
sodipodi:cx="8.1927567"
|
||||
sodipodi:cy="40.006229"
|
||||
sodipodi:rx="5.4535012"
|
||||
sodipodi:ry="5.4535012"
|
||||
d="m 3.8969257,36.646689 a 5.4535012,5.4535012 0 0 1 4.2686858,-2.093893 l 0.027145,5.453433 z"
|
||||
sodipodi:start="3.8052902"
|
||||
sodipodi:end="4.7074114" />
|
||||
<circle
|
||||
id="path34778"
|
||||
style="fill:#f3f3f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.36248925;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
cx="8.1309881"
|
||||
cy="40.029209"
|
||||
r="0.91594833" />
|
||||
<path
|
||||
id="path35559"
|
||||
d="M 7.4055247,39.313544 4.135537,36.5667"
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.36248925;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path35561"
|
||||
d="M 6.4021514,42.59715 7.4751372,40.968385"
|
||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.72497851;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<circle
|
||||
id="path35563"
|
||||
style="opacity:1;fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
|
||||
cx="7.9325924"
|
||||
cy="34.972736"
|
||||
r="0.61665297" />
|
||||
<circle
|
||||
id="path35565"
|
||||
style="opacity:1;fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
|
||||
cx="7.9325924"
|
||||
cy="44.839195"
|
||||
r="0.61665297" />
|
||||
<circle
|
||||
id="path35567"
|
||||
style="opacity:1;fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
|
||||
cx="2.9993658"
|
||||
cy="39.905964"
|
||||
r="0.61665297" />
|
||||
<circle
|
||||
id="path35569"
|
||||
style="opacity:1;fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
|
||||
cx="12.865818"
|
||||
cy="39.905964"
|
||||
r="0.61665297" />
|
||||
<circle
|
||||
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient4309);stroke-width:0.36248961;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path10651"
|
||||
cx="8.0055075"
|
||||
cy="39.946884"
|
||||
r="7.3380861" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 13 KiB |
BIN
orchestra/static/orchestra/images/reload.png
Normal file
BIN
orchestra/static/orchestra/images/reload.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 828 B |
207
orchestra/static/orchestra/images/reload.svg
Normal file
207
orchestra/static/orchestra/images/reload.svg
Normal file
|
@ -0,0 +1,207 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="16"
|
||||
height="16"
|
||||
id="svg2473"
|
||||
inkscape:version="0.91 r"
|
||||
sodipodi:docname="reload.svg"
|
||||
inkscape:export-filename="/home/glic3/orchestra/django-orchestra/orchestra/static/orchestra/images/reload.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<metadata
|
||||
id="metadata37">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1024"
|
||||
id="namedview35"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.75"
|
||||
inkscape:cx="-3.3220339"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2473" />
|
||||
<defs
|
||||
id="defs2475">
|
||||
<linearGradient
|
||||
id="linearGradient3719">
|
||||
<stop
|
||||
id="stop3721"
|
||||
style="stop-color:#538ec6;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3723"
|
||||
style="stop-color:#538ec6;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3709">
|
||||
<stop
|
||||
id="stop3711"
|
||||
style="stop-color:#6396cd;stop-opacity:0"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3713"
|
||||
style="stop-color:#6396cd;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3533">
|
||||
<stop
|
||||
id="stop3535"
|
||||
style="stop-color:#93b9dd;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3545"
|
||||
style="stop-color:#6396cd;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="108.97799"
|
||||
y1="230.02158"
|
||||
x2="107.36588"
|
||||
y2="224.30264"
|
||||
id="linearGradient6283"
|
||||
xlink:href="#linearGradient6277"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient6277">
|
||||
<stop
|
||||
id="stop6279"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop6281"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="107.25907"
|
||||
y1="222.87531"
|
||||
x2="108.83574"
|
||||
y2="226.83432"
|
||||
id="linearGradient6291"
|
||||
xlink:href="#linearGradient6285"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient6285">
|
||||
<stop
|
||||
id="stop6287"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop6289"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="8"
|
||||
y1="0"
|
||||
x2="9"
|
||||
y2="9"
|
||||
id="linearGradient3697"
|
||||
xlink:href="#linearGradient3533"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
x1="107.98247"
|
||||
y1="219.63542"
|
||||
x2="108.84705"
|
||||
y2="227.40942"
|
||||
id="linearGradient3705"
|
||||
xlink:href="#linearGradient3533"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
x1="112.3054"
|
||||
y1="227.40942"
|
||||
x2="108.84705"
|
||||
y2="230.86455"
|
||||
id="linearGradient3715"
|
||||
xlink:href="#linearGradient3709"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
x1="110.58552"
|
||||
y1="230.02382"
|
||||
x2="114.06341"
|
||||
y2="227.41991"
|
||||
id="linearGradient3725"
|
||||
xlink:href="#linearGradient3719"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(-103,-219)"
|
||||
id="g6293"
|
||||
style="stroke:#000000;stroke-opacity:1;display:inline;enable-background:new">
|
||||
<path
|
||||
d="m 112.89199,228.29933 a 4.75,4.75 0 0 1 -6.41224,0.8092"
|
||||
transform="matrix(1.1501219,0,0,1.1521155,-15.186827,-33.014002)"
|
||||
id="path4517-5"
|
||||
style="color:#000000;fill:none;stroke:url(#linearGradient3725);stroke-width:3.47488189;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 116,221 0,4 -4,0"
|
||||
id="path4519-1-9"
|
||||
style="fill:none;stroke:#538ec6;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 106.86806,229.35961 a 4.75,4.75 0 1 1 6.22978,-6.89468"
|
||||
transform="matrix(1.1501219,0,0,1.1521155,-15.186827,-33.014002)"
|
||||
id="path3717"
|
||||
style="color:#000000;fill:none;stroke:#538ec6;stroke-width:3.47488189;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<path
|
||||
d="m 107.99194,229.83037 a 4.75,4.75 0 1 1 5.1059,-7.36544"
|
||||
transform="matrix(1.1566222,0,0,1.1577034,-118.89492,-253.27267)"
|
||||
id="path4517"
|
||||
style="color:#000000;fill:none;stroke:url(#linearGradient3705);stroke-width:1.72836542;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 12.999998,2 0,4 -4.0000006,0"
|
||||
id="path4519-7"
|
||||
style="fill:none;stroke:url(#linearGradient3697);stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
|
||||
<path
|
||||
d="m 11,5.5 -2.0000026,0 M 12.499998,2 l 0,1.3"
|
||||
id="path4519-8-7"
|
||||
style="opacity:0.23999999;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
|
||||
<path
|
||||
d="m 112.88153,228.31178 a 4.75,4.75 0 0 1 -5.33461,1.37241"
|
||||
transform="matrix(1.1566222,0,0,1.1577034,-118.89492,-253.27267)"
|
||||
id="path3707"
|
||||
style="color:#000000;fill:none;stroke:url(#linearGradient3715);stroke-width:1.72836542;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 106.51558,229.134 a 4.75,4.75 0 1 1 6.58226,-6.66907"
|
||||
transform="matrix(1.2684974,0,0,1.2629385,-131.05785,-276.9778)"
|
||||
id="path4517-8"
|
||||
style="opacity:0.23999999;color:#000000;fill:none;stroke:url(#linearGradient6291);stroke-width:0.79006732;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 111.90936,229.18578 a 4.75,4.75 0 1 1 1.18848,-6.72085"
|
||||
transform="matrix(1.0467613,0,0,1.0546091,-106.88644,-230.0516)"
|
||||
id="path4517-8-9"
|
||||
style="opacity:0.23999999;color:#000000;fill:none;stroke:url(#linearGradient6283);stroke-width:0.95176643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</svg>
|
After Width: | Height: | Size: 8.1 KiB |
|
@ -32,6 +32,7 @@
|
|||
<p>{{ content_message | safe }}</p>
|
||||
<ul>{{ display_objects | unordered_list }}</ul>
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
{% block form %}
|
||||
{% if form %}
|
||||
<fieldset class="module aligned">
|
||||
{{ form.non_field_errors }}
|
||||
|
@ -50,9 +51,12 @@
|
|||
{% endfor %}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block formset %}
|
||||
{% if formset %}
|
||||
{{ formset.as_admin }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
<div>
|
||||
{% for obj in queryset %}
|
||||
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
|
||||
|
|
|
@ -40,7 +40,7 @@ def _un(singular__plural, n=None):
|
|||
return ungettext(singular, plural, n)
|
||||
|
||||
|
||||
def naturaldatetime(date, include_seconds=False):
|
||||
def naturaldatetime(date, include_seconds=True):
|
||||
"""Convert datetime into a human natural date string."""
|
||||
if not date:
|
||||
return ''
|
||||
|
@ -56,35 +56,35 @@ def naturaldatetime(date, include_seconds=False):
|
|||
minutes = delta.seconds / 60
|
||||
seconds = delta.seconds
|
||||
|
||||
ago = ' ago'
|
||||
ago = " ago"
|
||||
if days < 0:
|
||||
ago = ''
|
||||
ago = ""
|
||||
days = abs(days)
|
||||
|
||||
if days == 0:
|
||||
if hours == 0:
|
||||
if minutes > 0:
|
||||
if minutes >= 1:
|
||||
minutes = float(seconds)/60
|
||||
return ungettext(
|
||||
_('{minutes:.1f} minute{ago}'),
|
||||
_('{minutes:.1f} minutes{ago}'), minutes
|
||||
_("{minutes:.1f} minute{ago}"),
|
||||
_("{minutes:.1f} minutes{ago}"), minutes
|
||||
).format(minutes=minutes, ago=ago)
|
||||
else:
|
||||
if include_seconds and seconds:
|
||||
if include_seconds:
|
||||
return ungettext(
|
||||
_('{seconds} second{ago}'),
|
||||
_('{seconds} seconds{ago}'), seconds
|
||||
_("{seconds} second{ago}"),
|
||||
_("{seconds} seconds{ago}"), seconds
|
||||
).format(seconds=seconds, ago=ago)
|
||||
return _('just now')
|
||||
return _("just now")
|
||||
else:
|
||||
hours = float(minutes)/60
|
||||
return ungettext(
|
||||
_('{hours:.1f} hour{ago}'),
|
||||
_('{hours:.1f} hours{ago}'), hours
|
||||
_("{hours:.1f} hour{ago}"),
|
||||
_("{hours:.1f} hours{ago}"), hours
|
||||
).format(hours=hours, ago=ago)
|
||||
|
||||
if delta_midnight.days == 0:
|
||||
return _('yesterday at {time}').format(time=date.strftime('%H:%M'))
|
||||
return _("yesterday at {time}").format(time=date.strftime('%H:%M'))
|
||||
|
||||
count = 0
|
||||
for chunk, pluralizefun in OLDER_CHUNKS:
|
||||
|
|
Loading…
Reference in a new issue