Webapps massive refactoring

This commit is contained in:
Marc Aymerich 2015-03-04 21:06:16 +00:00
parent 7c5165f753
commit 12910bf072
82 changed files with 5118 additions and 487 deletions

View File

@ -190,7 +190,6 @@ Multi-tenant WebApps
* forms autocomplete="off", doesn't work in chrome
ln -s /proc/self/fd /dev/fd
@ -204,3 +203,6 @@ POST INSTALL
ssh-keygen
ssh-copy-id root@<server-address>
* symbolicLink webapp (link stuff from other places)

View File

@ -161,6 +161,22 @@ class AccountAdminMixin(object):
account_link.allow_tags = True
account_link.admin_order_field = 'account__username'
def get_fields(self, request, obj=None):
""" remove account or account_link depending on the case """
fields = super(AccountAdminMixin, self).get_fields(request, obj)
fields = list(fields)
if obj is not None or getattr(self, 'account_id', None):
try:
fields.remove('account')
except ValueError:
pass
else:
try:
fields.remove('account_link')
except ValueError:
pass
return fields
def get_readonly_fields(self, request, obj=None):
""" provide account for filter_by_account_fields """
if obj:

View File

@ -11,6 +11,7 @@ from . import settings
class MySQLBackend(ServiceController):
verbose_name = "MySQL database"
model = 'databases.Database'
default_route_match = "database.type == 'mysql'"
def save(self, database):
if database.type != database.MYSQL:
@ -53,6 +54,7 @@ class MySQLBackend(ServiceController):
class MySQLUserBackend(ServiceController):
verbose_name = "MySQL user"
model = 'databases.DatabaseUser'
default_route_match = "databaseuser.type == 'mysql'"
def save(self, user):
if user.type != user.MYSQL:

View File

@ -37,7 +37,9 @@ class Database(models.Model):
return users.order_by('id').first().databaseuser
Database.users.through._meta.unique_together = (('database', 'databaseuser'),)
Database.users.through._meta.unique_together = (
('database', 'databaseuser'),
)
class DatabaseUser(models.Model):

View File

@ -4,6 +4,7 @@ import textwrap
from django.utils.translation import ugettext_lazy as _
from orchestra.apps.orchestration import ServiceController
from orchestra.apps.orchestration.models import BackendOperation as Operation
from orchestra.utils.python import AttrDict
from . import settings
@ -75,10 +76,11 @@ class Bind9MasterDomainBackend(ServiceController):
self.append('[[ $UPDATED == 1 ]] && service bind9 reload')
def get_servers(self, domain, backend):
from orchestra.apps.orchestration.models import Route
operation = AttrDict(backend=backend, action='save', instance=domain)
""" Get related server IPs from registered backend routes """
from orchestra.apps.orchestration.manager import router
operation = Operation.create(backend_cls=backend, action=Operation.SAVE, instance=domain)
servers = []
for server in Route.get_servers(operation):
for server in router.get_servers(operation):
servers.append(server.get_ip())
return servers

View File

@ -96,7 +96,14 @@ class Domain(models.Model):
def render_zone(self):
origin = self.origin
zone = origin.render_records()
tail = []
for subdomain in origin.get_subdomains():
if subdomain.name.startswith('*'):
# This subdomains needs to be rendered last in order to avoid undesired matches
tail.append(subdomain)
else:
zone += subdomain.render_records()
for subdomain in sorted(tail, key=lambda x: len(x.name), reverse=True):
zone += subdomain.render_records()
return zone

View File

@ -3,13 +3,12 @@ from django.contrib import admin
from django.utils.html import escape
from django.utils.translation import ugettext_lazy as _
from orchestra.forms.widgets import DynamicHelpTextSelect
from orchestra.admin.html import monospace_format
from orchestra.admin.utils import admin_link, admin_date, admin_colored
from .backends import ServiceBackend
from .models import Server, Route, BackendLog, BackendOperation
from .widgets import RouteBackendSelect
STATE_COLORS = {
BackendLog.RECEIVED: 'darkorange',
@ -22,18 +21,22 @@ STATE_COLORS = {
}
class RouteAdmin(admin.ModelAdmin):
list_display = [
'id', 'backend', 'host', 'match', 'display_model', 'display_actions',
'is_active'
]
list_editable = ['backend', 'host', 'match', 'is_active']
list_editable = ['host', 'match', 'is_active']
list_filter = ['host', 'is_active', 'backend']
BACKEND_HELP_TEXT = {
backend: "This backend operates over '%s'" % ServiceBackend.get_backend(backend).model
for backend, __ in ServiceBackend.get_plugin_choices()
}
DEFAULT_MATCH = {
backend.get_name(): backend.default_route_match for backend in ServiceBackend.get_backends(active=False)
}
def display_model(self, route):
try:
@ -54,7 +57,7 @@ class RouteAdmin(admin.ModelAdmin):
def formfield_for_dbfield(self, db_field, **kwargs):
""" Provides dynamic help text on backend form field """
if db_field.name == 'backend':
kwargs['widget'] = DynamicHelpTextSelect('this.id', self.BACKEND_HELP_TEXT)
kwargs['widget'] = RouteBackendSelect('this.id', self.BACKEND_HELP_TEXT, self.DEFAULT_MATCH)
return super(RouteAdmin, self).formfield_for_dbfield(db_field, **kwargs)
def get_form(self, request, obj=None, **kwargs):

View File

@ -34,6 +34,7 @@ class ServiceBackend(plugins.Plugin):
type = 'task' # 'sync'
ignore_fields = []
actions = []
default_route_match = 'True'
__metaclass__ = ServiceMount

View File

@ -10,6 +10,7 @@ from .helpers import send_report
logger = logging.getLogger(__name__)
router = import_class(settings.ORCHESTRATION_ROUTER)
def as_task(execute):
@ -41,17 +42,17 @@ def close_connection(execute):
def execute(operations, async=False):
""" generates and executes the operations on the servers """
router = import_class(settings.ORCHESTRATION_ROUTER)
scripts = {}
cache = {}
# Generate scripts per server+backend
for operation in operations:
logger.debug("Queued %s" % str(operation))
servers = router.get_servers(operation, cache=cache)
for server in servers:
if operation.servers is None:
operation.servers = router.get_servers(operation, cache=cache)
for server in operation.servers:
key = (server, operation.backend)
if key not in scripts:
scripts[key] = (operation.backend(), [operation])
scripts[key] = (operation.backend, [operation])
scripts[key][0].prepare()
else:
scripts[key][1].append(operation)

View File

@ -7,6 +7,7 @@ from django.http.response import HttpResponseServerError
from orchestra.utils.python import OrderedSet
from .manager import router
from .backends import ServiceBackend
from .helpers import message_user
from .models import BackendLog
@ -51,6 +52,16 @@ class OperationsMiddleware(object):
return request.pending_operations
return set()
@classmethod
def get_route_cache(cls):
""" chache the routes to save sql queries """
if hasattr(cls.thread_locals, 'request'):
request = cls.thread_locals.request
if not hasattr(request, 'route_cache'):
request.route_cache = {}
return request.route_cache
return {}
@classmethod
def collect(cls, action, **kwargs):
""" Collects all pending operations derived from model signals """
@ -58,13 +69,14 @@ class OperationsMiddleware(object):
if request is None:
return
pending_operations = cls.get_pending_operations()
for backend in ServiceBackend.get_backends():
route_cache = cls.get_route_cache()
for backend_cls in ServiceBackend.get_backends():
# Check if there exists a related instance to be executed for this backend
instances = []
if backend.is_main(kwargs['instance']):
if backend_cls.is_main(kwargs['instance']):
instances = [(kwargs['instance'], action)]
else:
candidate = backend.get_related(kwargs['instance'])
candidate = backend_cls.get_related(kwargs['instance'])
if candidate:
if candidate.__class__.__name__ == 'ManyRelatedManager':
if 'pk_set' in kwargs:
@ -76,7 +88,7 @@ class OperationsMiddleware(object):
candidates = [candidate]
for candidate in candidates:
# Check if a delete for candidate is in pending_operations
delete_mock = Operation.create(backend, candidate, Operation.DELETE)
delete_mock = Operation.create(backend_cls, candidate, Operation.DELETE)
if delete_mock not in pending_operations:
# related objects with backend.model trigger save()
instances.append((candidate, Operation.SAVE))
@ -84,7 +96,7 @@ class OperationsMiddleware(object):
# Maintain consistent state of pending_operations based on save/delete behaviour
# Prevent creating a deleted instance by deleting existing saves
if iaction == Operation.DELETE:
save_mock = Operation.create(backend, instance, Operation.SAVE)
save_mock = Operation.create(backend_cls, instance, Operation.SAVE)
try:
pending_operations.remove(save_mock)
except KeyError:
@ -97,16 +109,22 @@ class OperationsMiddleware(object):
if update_fields != []:
execute = False
for field in update_fields:
if field not in backend.ignore_fields:
if field not in backend_cls.ignore_fields:
execute = True
break
if not execute:
continue
operation = Operation.create(backend, instance, iaction)
operation = Operation.create(backend_cls, instance, iaction)
# Only schedule operations if the router gives servers to execute into
servers = router.get_servers(operation, cache=route_cache)
if servers:
operation.servers = servers
if iaction != Operation.DELETE:
# usually we expect to be using last object state,
# except when we are deleting it
pending_operations.discard(operation)
elif iaction == Operation.DELETE:
operation.preload_context()
pending_operations.add(operation)
def process_request(self, request):

View File

@ -11,7 +11,7 @@ from orchestra.core.validators import validate_ip_address, ValidationError
from orchestra.models.fields import NullableCharField
#from orchestra.utils.apps import autodiscover
from . import settings, manager
from . import settings
from .backends import ServiceBackend
@ -119,36 +119,43 @@ class BackendOperation(models.Model):
def __hash__(self):
""" set() """
backend = getattr(self, 'backend', self.backend)
return hash(backend) + hash(self.instance) + hash(self.action)
backend_cls = type(self.backend)
return hash(backend_cls) + hash(self.instance) + hash(self.action)
def __eq__(self, operation):
""" set() """
return hash(self) == hash(operation)
@classmethod
def create(cls, backend, instance, action):
op = cls(backend=backend.get_name(), instance=instance, action=action)
op.backend = backend
def create(cls, backend_cls, instance, action, servers=None):
op = cls(backend=backend_cls.get_name(), instance=instance, action=action)
op.backend = backend_cls()
# instance should maintain any dynamic attribute until backend execution
# deep copy is prefered over copy otherwise objects will share same atributes (queryset cache)
op.instance = copy.deepcopy(instance)
if action == cls.DELETE:
# Heuristic, running get_context will prevent most of related objects do not exist errors
if hasattr(backend, 'get_context'):
backend().get_context(op.instance)
op.servers = servers
return op
@classmethod
def execute(cls, operations, async=False):
from . import manager
return manager.execute(operations, async=async)
@classmethod
def execute_action(cls, instance, action):
backends = ServiceBackend.get_backends(instance=instance, action=action)
operations = [cls.create(backend, instance, action) for backend in backends]
operations = [cls.create(backend_cls, instance, action) for backend_cls in backends]
return cls.execute(operations)
def preload_context(self):
"""
Heuristic
Running get_context will prevent most of related objects do not exist errors
"""
if self.action == self.DELETE:
if hasattr(self.backend, 'get_context'):
self.backend.get_context(op.instance)
def backend_class(self):
return ServiceBackend.get_backend(self.backend)
@ -187,14 +194,14 @@ class Route(models.Model):
def get_servers(cls, operation, **kwargs):
cache = kwargs.get('cache', {})
servers = []
backend = operation.backend
key = (backend.get_name(), operation.action)
backend_cls = type(operation.backend)
key = (backend_cls.get_name(), operation.action)
try:
routes = cache[key]
except KeyError:
cache[key] = []
for route in cls.objects.filter(is_active=True, backend=backend.get_name()):
for action in backend.get_actions():
for route in cls.objects.filter(is_active=True, backend=backend_cls.get_name()):
for action in backend_cls.get_actions():
_key = (route.backend, action)
try:
cache[_key].append(route)

View File

@ -0,0 +1,24 @@
import textwrap
from orchestra.forms.widgets import DynamicHelpTextSelect
class RouteBackendSelect(DynamicHelpTextSelect):
""" Updates matches input field based on selected backend """
def __init__(self, target, help_text, route_matches, *args, **kwargs):
kwargs['attrs'] = {
'onfocus': "this.oldvalue = this.value;",
}
self.route_matches = route_matches
super(RouteBackendSelect, self).__init__(target, help_text, *args, **kwargs)
def get_dynamic_help_text(self, target, help_text):
help_text = super(RouteBackendSelect, self).get_dynamic_help_text(target, help_text)
return help_text + textwrap.dedent("""\
routematches = {route_matches};
match = $("#id_match");
if ( this.oldvalue == "" || match.value == routematches[this.oldvalue])
match.value = routematches[this.options[this.selectedIndex].value];
this.oldvalue = this.value;
""".format(route_matches=self.route_matches)
)

View File

@ -33,25 +33,30 @@ class PaymentSource(models.Model):
def method_class(self):
return PaymentMethod.get_plugin(self.method)
@cached_property
def service_instance(self):
""" Per request lived method_instance """
return self.method_class()
@cached_property
def label(self):
return self.method_class().get_label(self.data)
return self.method_instance.get_label(self.data)
@cached_property
def number(self):
return self.method_class().get_number(self.data)
return self.method_instance.get_number(self.data)
def get_bill_context(self):
method = self.method_class()
method = self.method_instance
return {
'message': method.get_bill_message(self),
}
def get_due_delta(self):
return self.method_class().due_delta
return self.method_instance.due_delta
def clean(self):
self.data = self.method_class().clean_data(self.data)
self.data = self.method_instance.clean_data(self.data)
class TransactionQuerySet(models.QuerySet):

View File

@ -13,6 +13,7 @@ class SaaSAdmin(SelectPluginAdminMixin, AccountAdminMixin, admin.ModelAdmin):
list_filter = ('service',)
plugin = SoftwareService
plugin_field = 'service'
plugin_title = 'Software as a Service'
def display_site_name(self, saas):
site_name = saas.get_site_name()
@ -21,14 +22,5 @@ class SaaSAdmin(SelectPluginAdminMixin, AccountAdminMixin, admin.ModelAdmin):
display_site_name.allow_tags = True
display_site_name.admin_order_field = 'site_name'
def get_fields(self, request, obj=None):
fields = super(SaaSAdmin, self).get_fields(request, obj)
fields = list(fields)
# TODO do it in AccountAdminMixin?
if obj is not None:
fields.remove('account')
else:
fields.remove('account_link')
return fields
admin.site.register(SaaS, SaaSAdmin)

View File

@ -35,11 +35,16 @@ class SaaS(models.Model):
def service_class(self):
return SoftwareService.get_plugin(self.service)
@cached_property
def service_instance(self):
""" Per request lived service_instance """
return self.service_class()
def get_site_name(self):
return self.service_class().get_site_name(self)
return self.service_instance.get_site_name(self)
def clean(self):
self.data = self.service_class().clean_data(self)
self.data = self.service_instance.clean_data(self)
def set_password(self, password):
self.password = password

View File

@ -22,7 +22,7 @@ class BSCWService(SoftwareService):
verbose_name = "BSCW"
form = BSCWForm
serializer = BSCWDataSerializer
icon = 'saas/icons/BSCW.png'
icon = 'orchestra/icons/apps/BSCW.png'
# TODO override from settings
site_name = 'bascw.orchestra.lan'
change_readonly_fileds = ('email',)

View File

@ -3,4 +3,4 @@ from .options import SoftwareService
class GitLabService(SoftwareService):
verbose_name = "GitLab"
icon = 'saas/icons/gitlab.png'
icon = 'orchestra/icons/apps/gitlab.png'

View File

@ -17,4 +17,4 @@ class MoodleService(SoftwareService):
verbose_name = "Moodle"
form = MoodleForm
description_field = 'site_name'
icon = 'saas/icons/Moodle.png'
icon = 'orchestra/icons/apps/Moodle.png'

View File

@ -29,12 +29,6 @@ class SoftwareServiceForm(PluginDataForm):
super(SoftwareServiceForm, self).__init__(*args, **kwargs)
self.is_change = bool(self.instance and self.instance.pk)
if self.is_change:
for field in self.plugin.change_readonly_fileds + ('username',):
value = getattr(self.instance, field, None) or self.instance.data[field]
self.fields[field].required = False
self.fields[field].widget = widgets.ReadOnlyWidget(value)
self.fields[field].help_text = None
site_name = self.instance.get_site_name()
self.fields['password1'].required = False
self.fields['password1'].widget = forms.HiddenInput()
@ -79,7 +73,7 @@ class SoftwareService(plugins.Plugin):
site_name = None
site_name_base_domain = 'orchestra.lan'
icon = 'orchestra/icons/apps.png'
change_readonly_fileds = ()
change_readonly_fileds = ('username',)
class_verbose_name = _("Software as a Service")
@classmethod
@ -98,6 +92,10 @@ class SoftwareService(plugins.Plugin):
raise ValidationError(serializer.errors)
return serializer.data
@classmethod
def get_change_readonly_fileds(cls):
return cls.change_readonly_fileds + ('username',)
def get_site_name(self, saas):
return self.site_name or '.'.join((saas.site_name, self.site_name_base_domain))

View File

@ -11,4 +11,4 @@ class PHPListForm(SoftwareServiceForm):
class PHPListService(SoftwareService):
verbose_name = "phpList"
form = PHPListForm
icon = 'saas/icons/Phplist.png'
icon = 'orchestra/icons/apps/Phplist.png'

View File

@ -115,7 +115,7 @@ class FTPTraffic(ServiceMonitor):
USERNAME="$3"
LOG_FILE="$4"
{
grep "UPLOAD\|DOWNLOAD" ${LOG_FILE} \\
grep " bytes, " ${LOG_FILE} \\
| grep " \\[${USERNAME}\\] " \\
| awk -v ini="${INI_DATE}" -v end="${END_DATE}" '
BEGIN {
@ -135,7 +135,7 @@ class FTPTraffic(ServiceMonitor):
} {
# Fri Jul 1 13:23:17 2014
split($4, time, ":")
day = sprintf("%02d", $3)
day = sprintf("%%02d", $3)
# line_date = year month day hour minute second
line_date = $5 months[$2] day time[1] time[2] time[3]
if ( line_date > ini && line_date < end) {

View File

@ -7,6 +7,7 @@ from orchestra.forms import UserCreationForm, UserChangeForm
from . import settings
from .models import SystemUser
class SystemUserFormMixin(object):
MOCK_USERNAME = '<username>'

View File

@ -7,8 +7,10 @@ from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.utils import change_url
from orchestra.apps.accounts.admin import AccountAdminMixin
from orchestra.forms.widgets import DynamicHelpTextSelect
from orchestra.plugins.admin import SelectPluginAdminMixin
from . import settings
from . import settings, options
from .applications import App
from .models import WebApp, WebAppOption
@ -17,8 +19,7 @@ class WebAppOptionInline(admin.TabularInline):
extra = 1
OPTIONS_HELP_TEXT = {
k: str(unicode(v[1])) if len(v) == 3 else ''
for k, v in settings.WEBAPPS_OPTIONS.iteritems()
op.name: str(unicode(op.help_text)) for op in options.get_enabled().values()
}
class Media:
@ -30,6 +31,12 @@ class WebAppOptionInline(admin.TabularInline):
if db_field.name == 'value':
kwargs['widget'] = forms.TextInput(attrs={'size':'100'})
if db_field.name == 'name':
if self.parent_object:
plugin = self.parent_object.type_class
else:
request = kwargs['request']
plugin = App.get_plugin(request.GET['type'])
kwargs['choices'] = plugin.get_options_choices()
# Help text based on select widget
kwargs['widget'] = DynamicHelpTextSelect(
'this.id.replace("name", "value")', self.OPTIONS_HELP_TEXT
@ -37,20 +44,22 @@ class WebAppOptionInline(admin.TabularInline):
return super(WebAppOptionInline, self).formfield_for_dbfield(db_field, **kwargs)
class WebAppAdmin(AccountAdminMixin, ExtendedModelAdmin):
class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin):
list_display = ('name', 'type', 'display_websites', 'account_link')
list_filter = ('type',)
add_fields = ('account', 'name', 'type')
fields = ('account_link', 'name', 'type')
# add_fields = ('account', 'name', 'type')
# fields = ('account_link', 'name', 'type')
inlines = [WebAppOptionInline]
readonly_fields = ('account_link',)
change_readonly_fields = ('name', 'type')
list_prefetch_related = ('content_set__website',)
plugin = App
plugin_field = 'type'
plugin_title = _("Web application type")
TYPE_HELP_TEXT = {
k: str(unicode(v.get('help_text', '')))
for k, v in settings.WEBAPPS_TYPES.iteritems()
}
# TYPE_HELP_TEXT = {
# app.get_name(): str(unicode(app.help_text)) for app in App.get_plugins()
# }
def display_websites(self, webapp):
websites = []
@ -68,14 +77,14 @@ class WebAppAdmin(AccountAdminMixin, ExtendedModelAdmin):
display_websites.short_description = _("web sites")
display_websites.allow_tags = True
def formfield_for_dbfield(self, db_field, **kwargs):
""" Make value input widget bigger """
if db_field.name == 'type':
# Help text based on select widget
kwargs['widget'] = DynamicHelpTextSelect(
'this.id.replace("name", "value")', self.TYPE_HELP_TEXT
)
kwargs['help_text'] = self.TYPE_HELP_TEXT.get(db_field.default, '')
return super(WebAppAdmin, self).formfield_for_dbfield(db_field, **kwargs)
# def formfield_for_dbfield(self, db_field, **kwargs):
# """ Make value input widget bigger """
# if db_field.name == 'type':
# # Help text based on select widget
# kwargs['widget'] = DynamicHelpTextSelect(
# 'this.id.replace("name", "value")', self.TYPE_HELP_TEXT
# )
# kwargs['help_text'] = self.TYPE_HELP_TEXT.get(db_field.default, '')
# return super(WebAppAdmin, self).formfield_for_dbfield(db_field, **kwargs)
admin.site.register(WebApp, WebAppAdmin)

View File

@ -12,16 +12,8 @@ class WebAppServiceMixin(object):
return settings.WEBAPPS_TYPES[webapp.type]['directive'][0] == self.directive
def create_webapp_dir(self, context):
self.append(textwrap.dedent("""
path=""
for dir in $(echo %(app_path)s | tr "/" "\n"); do
path="${path}/${dir}"
[ -d $path ] || {
mkdir "${path}"
chown %(user)s:%(group)s "${path}"
}
done
""" % context))
self.append("mkdir -p %(app_path)s" % context)
self.append("chown %(user)s:%(group)s %(app_path)s" % context)
def get_php_init_vars(self, webapp, per_account=False):
"""
@ -54,7 +46,7 @@ class WebAppServiceMixin(object):
return {
'user': webapp.get_username(),
'group': webapp.get_groupname(),
'app_name': webapp.get_name(),
'app_name': webapp.name,
'type': webapp.type,
'app_path': webapp.get_path().rstrip('/'),
'banner': self.get_banner(),

View File

@ -13,6 +13,7 @@ class PHPFcgidBackend(WebAppServiceMixin, ServiceController):
""" Per-webapp fcgid application """
verbose_name = _("PHP-Fcgid")
directive = 'fcgi'
default_route_match = "webapp.type.endswith('-fcgi')"
def save(self, webapp):
if not self.valid_directive(webapp):

View File

@ -14,6 +14,7 @@ class PHPFPMBackend(WebAppServiceMixin, ServiceController):
""" Per-webapp php application """
verbose_name = _("PHP-FPM")
directive = 'fpm'
default_route_match = "webapp.type.endswith('-fpm')"
def save(self, webapp):
if not self.valid_directive(webapp):
@ -26,7 +27,8 @@ class PHPFPMBackend(WebAppServiceMixin, ServiceController):
} || {
echo -e '%(fpm_config)s' > %(fpm_path)s
UPDATEDFPM=1
}""" % context))
}""" % context
))
def delete(self, webapp):
if not self.valid_directive(webapp):

View File

@ -8,6 +8,7 @@ from . import WebAppServiceMixin
class StaticBackend(WebAppServiceMixin, ServiceController):
verbose_name = _("Static")
directive = 'static'
default_route_match = "webapp.type == 'static'"
def save(self, webapp):
if not self.valid_directive(webapp):

View File

@ -0,0 +1,27 @@
from django.utils.translation import ugettext_lazy as _
from orchestra.apps.orchestration import ServiceController
from . import WebAppServiceMixin
class SymbolicLinkBackend(WebAppServiceMixin, ServiceController):
verbose_name = _("Symbolic link webapp")
model = 'webapps.WebApp'
default_route_match = "webapp.type == 'symbolic-link'"
def save(self, webapp):
context = self.get_context(webapp)
self.append("ln -s '%(link_path)s' %(app_path)s" % context)
self.append("chown -h %(user)s:%(group)s %(app_path)s" % context)
def delete(self, webapp):
context = self.get_context(webapp)
self.delete_webapp_dir(context)
def get_context(self, webapp):
context = super(SymbolicLinkBackend, self).get_context(webapp)
context.update({
'link_path': webapp.data['path'],
})
return context

View File

@ -0,0 +1,48 @@
import textwrap
from django.utils.translation import ugettext_lazy as _
from orchestra.apps.orchestration import ServiceController
from .. import settings
from . import WebAppServiceMixin
class WordPressBackend(WebAppServiceMixin, ServiceController):
verbose_name = _("Wordpress")
model = 'webapps.WebApp'
default_route_match = "webapp.type == 'wordpress'"
def save(self, webapp):
context = self.get_context(webapp)
self.create_webapp_dir(context)
self.append(textwrap.dedent("""\
# Check if directory is empty befor doing anything
if [[ ! $(ls -A %(app_path)s) ]]; then
wget http://wordpress.org/latest.tar.gz -O - --no-check-certificate \\
| tar -xzvf - -C %(app_path)s --strip-components=1
cp %(app_path)s/wp-config-sample.php %(app_path)s/wp-config.php
sed -i "s/database_name_here/%(db_name)s/" %(app_path)s/wp-config.php
sed -i "s/username_here/%(db_user)s/" %(app_path)s/wp-config.php
sed -i "s/password_here/%(db_pass)s/" %(app_path)s/wp-config.php
sed -i "s/localhost/%(db_host)s/" %(app_path)s/wp-config.php
mkdir %(app_path)s/wp-content/uploads
chmod 750 %(app_path)s/wp-content/uploads
chown -R %(user)s:%(group)s %(app_path)s
fi""" % context
))
def delete(self, webapp):
context = self.get_context(webapp)
self.delete_webapp_dir(context)
def get_context(self, webapp):
context = super(WordPressBackend, self).get_context(webapp)
context.update({
'db_name': webapp.data['db_name'],
'db_user': webapp.data['db_user'],
'db_pass': webapp.data['db_pass'],
'db_host': settings.WEBAPPS_DEFAULT_MYSQL_DATABASE_HOST,
})
return context

View File

@ -11,6 +11,7 @@ from .. import settings
class WordpressMuBackend(ServiceController):
verbose_name = _("Wordpress multisite")
model = 'webapps.WebApp'
default_route_match = "webapp.type == 'wordpress-mu'"
@property
def script(self):
@ -85,7 +86,7 @@ class WordpressMuBackend(ServiceController):
self.validate_response(response)
def delete_blog(self, webapp, server):
# OH, I've enjoied so much coding this methods that I want to thanks
# OH, I've enjoied so much coding this methods that I want to thank
# the wordpress team for the excellent software they are producing
session = requests.Session()
self.login(session)

View File

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import orchestra.core.validators
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='WebApp',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(max_length=128, verbose_name='name', validators=[orchestra.core.validators.validate_name])),
('type', models.CharField(max_length=32, verbose_name='type', choices=[(b'dokuwiki-mu', b'DokuWiki (SaaS)'), (b'drupal-mu', b'Drupdal (SaaS)'), (b'php4-fcgi', b'PHP 4 FCGI'), (b'php5.2-fcgi', b'PHP 5.2 FCGI'), (b'php5.5-fpm', b'PHP 5.5 FPM'), (b'static', b'Static'), (b'symlink', b'Symbolic link'), (b'webalizer', b'Webalizer'), (b'wordpress', b'WordPress'), (b'wordpress-mu', b'WordPress (SaaS)')])),
('account', models.ForeignKey(related_name='webapps', verbose_name='Account', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Web App',
'verbose_name_plural': 'Web Apps',
},
bases=(models.Model,),
),
migrations.CreateModel(
name='WebAppOption',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(max_length=128, verbose_name='name', choices=[(b'PHP-allow_url_fopen', 'PHP - allow_url_fopen'), (b'PHP-allow_url_include', 'PHP - Allow URL include'), (b'PHP-auto_append_file', 'PHP - Auto append file'), (b'PHP-auto_prepend_file', 'PHP - Auto prepend file'), (b'PHP-date.timezone', 'PHP - date.timezone'), (b'PHP-default_socket_timeout', 'PHP - Default socket timeout'), (b'PHP-display_errors', 'PHP - Display errors'), (b'PHP-extension', 'PHP - Extension'), (b'PHP-magic_quotes_gpc', 'PHP - Magic quotes GPC'), (b'PHP-magic_quotes_runtime', 'PHP - Magic quotes runtime'), (b'PHP-magic_quotes_sybase', 'PHP - Magic quotes sybase'), (b'PHP-max_execution_time', 'PHP - Max execution time'), (b'PHP-max_input_time', 'PHP - Max input time'), (b'PHP-max_input_vars', 'PHP - Max input vars'), (b'PHP-memory_limit', 'PHP - Memory limit'), (b'PHP-mysql.connect_timeout', 'PHP - Mysql connect timeout'), (b'PHP-output_buffering', 'PHP - output_buffering'), (b'PHP-post_max_size', 'PHP - Post max size'), (b'PHP-register_globals', 'PHP - Register globals'), (b'PHP-safe_mode', 'PHP - Safe mode'), (b'PHP-sendmail_path', 'PHP - sendmail_path'), (b'PHP-session.auto_start', 'PHP - session.auto_start'), (b'PHP-session.bug_compat_warn', 'PHP - session.bug_compat_warn'), (b'PHP-suhosin.executor.include.whitelist', 'PHP - suhosin.executor.include.whitelist'), (b'PHP-suhosin.get.max_vars', 'PHP - Suhosin GET max vars'), (b'PHP-suhosin.post.max_vars', 'PHP - Suhosin POST max vars'), (b'PHP-suhosin.request.max_vars', 'PHP - Suhosin request max vars'), (b'PHP-suhosin.session.encrypt', 'PHP - suhosin.session.encrypt'), (b'PHP-suhosin.simulation', 'PHP - Suhosin simulation'), (b'PHP-upload_max_filesize', 'PHP - upload_max_filesize'), (b'PHP-zend_extension', 'PHP - zend_extension'), (b'php-enabled_functions', 'PHP - Enabled functions'), (b'processes', 'Number of processes'), (b'public-root', 'Public root'), (b'timeout', 'Process timeout')])),
('value', models.CharField(max_length=256, verbose_name='value')),
('webapp', models.ForeignKey(related_name='options', verbose_name='Web application', to='webapps.WebApp')),
],
options={
'verbose_name': 'option',
'verbose_name_plural': 'options',
},
bases=(models.Model,),
),
migrations.AlterUniqueTogether(
name='webappoption',
unique_together=set([('webapp', 'name')]),
),
migrations.AlterUniqueTogether(
name='webapp',
unique_together=set([('name', 'account')]),
),
]

View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import jsonfield.fields
class Migration(migrations.Migration):
dependencies = [
('webapps', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='webapp',
name='data',
field=jsonfield.fields.JSONField(default={}, help_text='Extra information dependent of each service.', verbose_name='data'),
preserve_default=False,
),
]

View File

@ -2,23 +2,25 @@ import re
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from jsonfield import JSONField
from orchestra.core import validators, services
from orchestra.utils import tuple_setting_to_choices, dict_setting_to_choices
from orchestra.utils.functional import cached
from . import settings
from . import settings, options
from .types import AppType
class WebApp(models.Model):
""" Represents a web application """
name = models.CharField(_("name"), max_length=128, validators=[validators.validate_name])
type = models.CharField(_("type"), max_length=32,
choices=dict_setting_to_choices(settings.WEBAPPS_TYPES),
default=settings.WEBAPPS_DEFAULT_TYPE)
choices=AppType.get_plugin_choices())
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
related_name='webapps')
data = JSONField(_("data"), help_text=_("Extra information dependent of each service."))
class Meta:
unique_together = ('name', 'account')
@ -31,21 +33,25 @@ class WebApp(models.Model):
def get_description(self):
return self.get_type_display()
@cached_property
def type_class(self):
return AppType.get_plugin(self.type)
@cached_property
def type_instance(self):
""" Per request lived type_instance """
return self.type_class()
def clean(self):
# Validate unique webapp names
if self.app_type.get('unique_name', False):
try:
webapp = WebApp.objects.exclude(id=self.pk).get(name=self.name, type=self.type)
except WebApp.DoesNotExist:
pass
else:
raise ValidationError({
'name': _("A webapp with this name already exists."),
})
apptype = self.type_instance
apptype.validate(self)
self.data = apptype.clean_data(self)
@cached
def get_options(self):
return { opt.name: opt.value for opt in self.options.all() }
return {
opt.name: opt.value for opt in self.options.all()
}
@property
def app_type(self):
@ -81,7 +87,7 @@ class WebAppOption(models.Model):
webapp = models.ForeignKey(WebApp, verbose_name=_("Web application"),
related_name='options')
name = models.CharField(_("name"), max_length=128,
choices=tuple_setting_to_choices(settings.WEBAPPS_OPTIONS))
choices=((op.name, op.verbose_name) for op in options.get_enabled().values()))
value = models.CharField(_("value"), max_length=256)
class Meta:
@ -93,16 +99,24 @@ class WebAppOption(models.Model):
return self.name
def clean(self):
""" validates name and value according to WEBAPPS_OPTIONS """
regex = settings.WEBAPPS_OPTIONS[self.name][-1]
if not re.match(regex, self.value):
raise ValidationError({
'value': ValidationError(_("'%(value)s' does not match %(regex)s."),
params={
'value': self.value,
'regex': regex
}),
})
option = options.get_enabled()[self.name]
option.validate(self)
services.register(WebApp)
# Admin bulk deletion doesn't call model.delete(), we use signals instead of model method overriding
from django.db.models.signals import pre_save, pre_delete
from django.dispatch import receiver
@receiver(pre_save, sender=WebApp, dispatch_uid='webapps.type.save')
def type_save(sender, *args, **kwargs):
instance = kwargs['instance']
instance.type_instance.save(instance)
@receiver(pre_delete, sender=WebApp, dispatch_uid='webapps.type.delete')
def type_delete(sender, *args, **kwargs):
instance = kwargs['instance']
instance.type_instance.delete(instance)

View File

@ -0,0 +1,300 @@
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from orchestra.utils.python import import_class
from . import settings
class AppOption(object):
def __init__(self, name, *args, **kwargs):
self.name = name
self.verbose_name = kwargs.pop('verbose_name', name)
self.help_text = kwargs.pop('help_text', '')
for k,v in kwargs.iteritems():
setattr(self, k, v)
def validate(self, webapp):
if self.regex and not re.match(self.regex, webapp.value):
raise ValidationError({
'value': ValidationError(_("'%(value)s' does not match %(regex)s."),
params={
'value': webapp.value,
'regex': self.regex
}),
})
public_root = AppOption('public-root',
verbose_name=_("Public root"),
help_text=_("Document root relative to webapps/&lt;webapp&gt;/"),
regex=r'[^ ]+'
)
timeout = AppOption('timeout',
# FCGID FcgidIOTimeout
# FPM pm.request_terminate_timeout
# PHP max_execution_time ini
verbose_name=_("Process timeout"),
help_text=_("Maximum time in seconds allowed for a request to complete (a number between 0 and 999)."),
regex=r'^[0-9]{1,3}$',
)
processes = AppOption('processes',
# FCGID MaxProcesses
# FPM pm.max_children
verbose_name=_("Number of processes"),
help_text=_("Maximum number of children that can be alive at the same time (a number between 0 and 9)."),
regex=r'^[0-9]$',
)
php_enabled_functions = AppOption('php-enabled_functions',
verbose_name=_("Enabled functions"),
help_text = ' '.join(settings.WEBAPPS_PHP_DISABLED_FUNCTIONS),
regex=r'^[\w\.,-]+$'
)
php_allow_url_include = AppOption('PHP-allow_url_include',
verbose_name=_("Allow URL include"),
help_text=_("Allows the use of URL-aware fopen wrappers with include, include_once, require, "
"require_once (On or Off)."),
regex=r'^(On|Off|on|off)$'
)
php_allow_url_fopen = AppOption('PHP-allow_url_fopen',
verbose_name=_("Allow URL fopen"),
help_text=_("Enables the URL-aware fopen wrappers that enable accessing URL object like files (On or Off)."),
regex=r'^(On|Off|on|off)$'
)
php_auto_append_file = AppOption('PHP-auto_append_file',
verbose_name=_("Auto append file"),
help_text=_("Specifies the name of a file that is automatically parsed after the main file."),
regex=r'^[\w\.,-/]+$'
)
php_auto_prepend_file = AppOption('PHP-auto_prepend_file',
verbose_name=_("Auto prepend file"),
help_text=_("Specifies the name of a file that is automatically parsed before the main file."),
regex=r'^[\w\.,-/]+$'
)
php_date_timezone = AppOption('PHP-date.timezone',
verbose_name=_("date.timezone"),
help_text=_("Sets the default timezone used by all date/time functions (Timezone string 'Europe/London')."),
regex=r'^\w+/\w+$'
)
php_default_socket_timeout = AppOption('PHP-default_socket_timeout',
verbose_name=_("Default socket timeout"),
help_text=_("Number between 0 and 999."),
regex=r'^[0-9]{1,3}$'
)
php_display_errors = AppOption('PHP-display_errors',
verbose_name=_("Display errors"),
help_text=_("Determines whether errors should be printed to the screen as part of the output or "
"if they should be hidden from the user (On or Off)."),
regex=r'^(On|Off|on|off)$'
)
php_extension = AppOption('PHP-extension',
verbose_name=_("Extension"),
regex=r'^[^ ]+$'
)
php_magic_quotes_gpc = AppOption('PHP-magic_quotes_gpc',
verbose_name=_("Magic quotes GPC"),
help_text=_("Sets the magic_quotes state for GPC (Get/Post/Cookie) operations (On or Off) "
"<b>DEPRECATED as of PHP 5.3.0</b>."),
regex=r'^(On|Off|on|off)$',
deprecated=5.3
)
php_magic_quotes_runtime = AppOption('PHP-magic_quotes_runtime',
verbose_name=_("Magic quotes runtime"),
help_text=_("Functions that return data from any sort of external source will have quotes escaped "
"with a backslash (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>."),
regex=r'^(On|Off|on|off)$',
deprecated=5.3
)
php_magic_quotes_sybase = AppOption('PHP-magic_quotes_sybase',
verbose_name=_("Magic quotes sybase"),
help_text=_("Single-quote is escaped with a single-quote instead of a backslash (On or Off)."),
regex=r'^(On|Off|on|off)$'
)
php_max_execution_time = AppOption('PHP-max_execution_time',
verbose_name=_("Max execution time"),
help_text=_("Maximum time in seconds a script is allowed to run before it is terminated by "
"the parser (Integer between 0 and 999)."),
regex=r'^[0-9]{1,3}$'
)
php_max_input_time = AppOption('PHP-max_input_time',
verbose_name=_("Max input time"),
help_text=_("Maximum time in seconds a script is allowed to parse input data, like POST and GET "
"(Integer between 0 and 999)."),
regex=r'^[0-9]{1,3}$'
)
php_max_input_vars = AppOption('PHP-max_input_vars',
verbose_name=_("Max input vars"),
help_text=_("How many input variables may be accepted (limit is applied to $_GET, $_POST "
"and $_COOKIE superglobal separately) (Integer between 0 and 9999)."),
regex=r'^[0-9]{1,4}$'
)
php_memory_limit = AppOption('PHP-memory_limit',
verbose_name=_("Memory limit"),
help_text=_("This sets the maximum amount of memory in bytes that a script is allowed to allocate "
"(Value between 0M and 999M)."),
regex=r'^[0-9]{1,3}M$'
)
php_mysql_connect_timeout = AppOption('PHP-mysql.connect_timeout',
verbose_name=_("Mysql connect timeout"),
help_text=_("Number between 0 and 999."),
regex=r'^([0-9]){1,3}$'
)
php_output_buffering = AppOption('PHP-output_buffering',
verbose_name=_("Output buffering"),
help_text=_("Turn on output buffering (On or Off)."),
regex=r'^(On|Off|on|off)$'
)
php_register_globals = AppOption('PHP-register_globals',
verbose_name=_("Register globals"),
help_text=_("Whether or not to register the EGPCS (Environment, GET, POST, Cookie, Server) "
"variables as global variables (On or Off)."),
regex=r'^(On|Off|on|off)$'
)
php_post_max_size = AppOption('PHP-post_max_size',
verbose_name=_("Post max size"),
help_text=_("Sets max size of post data allowed (Value between 0M and 999M)."),
regex=r'^[0-9]{1,3}M$'
)
php_sendmail_path = AppOption('PHP-sendmail_path',
verbose_name=_("sendmail_path"),
help_text=_("Where the sendmail program can be found."),
regex=r'^[^ ]+$'
)
php_session_bug_compat_warn = AppOption('PHP-session.bug_compat_warn',
verbose_name=_("session.bug_compat_warn"),
help_text=_("Enables an PHP bug on session initialization for legacy behaviour (On or Off)."),
regex=r'^(On|Off|on|off)$'
)
php_session_auto_start = AppOption('PHP-session.auto_start',
verbose_name=_("session.auto_start"),
help_text=_("Specifies whether the session module starts a session automatically on request "
"startup (On or Off)."),
regex=r'^(On|Off|on|off)$'
)
php_safe_mode = AppOption('PHP-safe_mode',
verbose_name=_("Safe mode"),
help_text=_("Whether to enable PHP's safe mode (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>"),
regex=r'^(On|Off|on|off)$',
deprecated=5.3
)
php_suhosin_post_max_vars = AppOption('PHP-suhosin.post.max_vars',
verbose_name=_("Suhosin POST max vars"),
help_text=_("Number between 0 and 9999."),
regex=r'^[0-9]{1,4}$'
)
php_suhosin_get_max_vars = AppOption('PHP-suhosin.get.max_vars',
verbose_name=_("Suhosin GET max vars"),
help_text=_("Number between 0 and 9999."),
regex=r'^[0-9]{1,4}$'
)
php_suhosin_request_max_vars = AppOption('PHP-suhosin.request.max_vars',
verbose_name=_("Suhosin request max vars"),
help_text=_("Number between 0 and 9999."),
regex=r'^[0-9]{1,4}$'
)
php_suhosin_session_encrypt = AppOption('PHP-suhosin.session.encrypt',
verbose_name=_("suhosin.session.encrypt"),
help_text=_("On or Off"),
regex=r'^(On|Off|on|off)$'
)
php_suhosin_simulation = AppOption('PHP-suhosin.simulation',
verbose_name=_("Suhosin simulation"),
help_text=_("On or Off"),
regex=r'^(On|Off|on|off)$'
)
php_suhosin_executor_include_whitelist = AppOption('PHP-suhosin.executor.include.whitelist',
verbose_name=_("suhosin.executor.include.whitelist"),
regex=r'.*$'
)
php_upload_max_filesize = AppOption('PHP-upload_max_filesize',
verbose_name=_("upload_max_filesize"),
help_text=_("Value between 0M and 999M."),
regex=r'^[0-9]{1,3}M$'
)
php_zend_extension = AppOption('PHP-post_max_size',
verbose_name=_("zend_extension"),
regex=r'^[^ ]+$'
)
filesystem = [
public_root,
]
process = [
timeout,
processes,
]
php = [
php_enabled_functions,
php_allow_url_include,
php_allow_url_fopen,
php_auto_append_file,
php_auto_prepend_file,
php_date_timezone,
php_default_socket_timeout,
php_display_errors,
php_extension,
php_magic_quotes_gpc,
php_magic_quotes_runtime,
php_magic_quotes_sybase,
php_max_execution_time,
php_max_input_time,
php_max_input_vars,
php_memory_limit,
php_mysql_connect_timeout,
php_output_buffering,
php_register_globals,
php_post_max_size,
php_sendmail_path,
php_session_bug_compat_warn,
php_session_auto_start,
php_safe_mode,
php_suhosin_post_max_vars,
php_suhosin_get_max_vars,
php_suhosin_request_max_vars,
php_suhosin_session_encrypt,
php_suhosin_simulation,
php_suhosin_executor_include_whitelist,
php_upload_max_filesize,
php_zend_extension,
]
_enabled = None
def get_enabled():
global _enabled
if _enabled is None:
from . import settings
_enabled = {}
for op in settings.WEBAPPS_ENABLED_OPTIONS:
op = import_class(op)
_enabled[op.name] = op
return _enabled

View File

@ -21,67 +21,26 @@ WEBAPPS_FCGID_PATH = getattr(settings, 'WEBAPPS_FCGID_PATH',
'/home/httpd/fcgid/%(user)s/%(app_name)s-wrapper')
WEBAPPS_TYPES = getattr(settings, 'WEBAPPS_TYPES', {
'php5.5': {
'verbose_name': "PHP 5.5 fpm",
# 'fpm', ('unix:/var/run/%(user)s-%(app_name)s.sock|fcgi://127.0.0.1%(app_path)s',),
'directive': ('fpm', 'fcgi://{}%(app_path)s'.format(WEBAPPS_FPM_LISTEN)),
'help_text': _("This creates a PHP5.5 application under ~/webapps/&lt;app_name&gt;<br>"
"PHP-FPM will be used to execute PHP files.")
},
'php5.2': {
'verbose_name': "PHP 5.2 fcgi",
'directive': ('fcgi', WEBAPPS_FCGID_PATH),
'help_text': _("This creates a PHP5.2 application under ~/webapps/&lt;app_name&gt;<br>"
"Apache-mod-fcgid will be used to execute PHP files.")
},
'php4': {
'verbose_name': "PHP 4 fcgi",
'directive': ('fcgi', WEBAPPS_FCGID_PATH,),
'help_text': _("This creates a PHP4 application under ~/webapps/&lt;app_name&gt;<br>"
"Apache-mod-fcgid will be used to execute PHP files.")
},
'static': {
'verbose_name': _("Static"),
'directive': ('static',),
'help_text': _("This creates a Static application under ~/webapps/&lt;app_name&gt;<br>"
"Apache2 will be used to serve static content and execute CGI files.")
},
'webalizer': {
'verbose_name': "Webalizer",
'directive': ('static', '%(app_path)s%(site_name)s'),
'help_text': _("This creates a Webalizer application under "
"~/webapps/&lt;app_name&gt;-&lt;site_name&gt;")
},
'wordpress-mu': {
'verbose_name': _("Wordpress (SaaS)"),
'directive': ('fpm', 'fcgi://127.0.0.1:8990/home/httpd/wordpress-mu/'),
'help_text': _("This creates a Wordpress site on a multi-tenant Wordpress server.<br>"
"By default this blog is accessible via &lt;app_name&gt;.blogs.orchestra.lan")
},
'dokuwiki-mu': {
'verbose_name': _("DokuWiki (SaaS)"),
'directive': ('alias', '/home/httpd/wikifarm/farm/'),
'help_text': _("This create a Dokuwiki wiki into a shared Dokuwiki server.<br>"
"By default this wiki is accessible via &lt;app_name&gt;.wikis.orchestra.lan")
},
'drupal-mu': {
'verbose_name': _("Drupdal (SaaS)"),
'directive': ('fpm', 'fcgi://127.0.0.1:8991/home/httpd/drupal-mu/'),
'help_text': _("This creates a Drupal site into a multi-tenant Drupal server.<br>"
"The installation will be completed after visiting "
"http://&lt;app_name&gt;.drupal.orchestra.lan/install.php?profile=standard<br>"
"By default this site will be accessible via &lt;app_name&gt;.drupal.orchestra.lan")
}
})
WEBAPPS_TYPES = getattr(settings, 'WEBAPPS_TYPES', (
'orchestra.apps.webapps.types.Php55App',
'orchestra.apps.webapps.types.Php52App',
'orchestra.apps.webapps.types.Php4App',
'orchestra.apps.webapps.types.StaticApp',
'orchestra.apps.webapps.types.WebalizerApp',
'orchestra.apps.webapps.types.WordPressMuApp',
'orchestra.apps.webapps.types.DokuWikiMuApp',
'orchestra.apps.webapps.types.DrupalMuApp',
'orchestra.apps.webapps.types.SymbolicLinkApp',
'orchestra.apps.webapps.types.WordPressApp',
))
WEBAPPS_TYPES_OVERRIDE = getattr(settings, 'WEBAPPS_TYPES_OVERRIDE', {})
for webapp_type, value in WEBAPPS_TYPES_OVERRIDE.iteritems():
if value is None:
WEBAPPS_TYPES.pop(webapp_type, None)
else:
WEBAPPS_TYPES[webapp_type] = value
#WEBAPPS_TYPES_OVERRIDE = getattr(settings, 'WEBAPPS_TYPES_OVERRIDE', {})
#for webapp_type, value in WEBAPPS_TYPES_OVERRIDE.iteritems():
# if value is None:
# WEBAPPS_TYPES.pop(webapp_type, None)
# else:
# WEBAPPS_TYPES[webapp_type] = value
WEBAPPS_DEFAULT_TYPE = getattr(settings, 'WEBAPPS_DEFAULT_TYPE', 'php5.5')
@ -116,204 +75,43 @@ WEBAPPS_PHP_DISABLED_FUNCTIONS = getattr(settings, 'WEBAPPS_PHP_DISABLED_FUNCTIO
])
WEBAPPS_OPTIONS = getattr(settings, 'WEBAPPS_OPTIONS', {
# { name: ( verbose_name, [help_text], validation_regex ) }
# Filesystem
'public-root': (
_("Public root"),
_("Document root relative to webapps/&lt;webapp&gt;/"),
r'[^ ]+',
),
# Processes
'timeout': (
_("Process timeout"),
_("Maximum time in seconds allowed for a request to complete "
"(a number between 0 and 999)."),
# FCGID FcgidIOTimeout
# FPM pm.request_terminate_timeout
# PHP max_execution_time ini
r'^[0-9]{1,3}$',
),
'processes': (
_("Number of processes"),
_("Maximum number of children that can be alive at the same time "
"(a number between 0 and 9)."),
# FCGID MaxProcesses
# FPM pm.max_children
r'^[0-9]$',
),
# PHP
'php-enabled_functions': (
_("PHP - Enabled functions"),
' '.join(WEBAPPS_PHP_DISABLED_FUNCTIONS),
r'^[\w\.,-]+$'
),
'PHP-allow_url_include': (
_("PHP - Allow URL include"),
_("Allows the use of URL-aware fopen wrappers with include, include_once, require, "
"require_once (On or Off)."),
r'^(On|Off|on|off)$'
),
'PHP-allow_url_fopen': (
_("PHP - allow_url_fopen"),
_("Enables the URL-aware fopen wrappers that enable accessing URL object like files "
"(On or Off)."),
r'^(On|Off|on|off)$'
),
'PHP-auto_append_file': (
_("PHP - Auto append file"),
_("Specifies the name of a file that is automatically parsed after the main file."),
r'^[\w\.,-/]+$'
),
'PHP-auto_prepend_file': (
_("PHP - Auto prepend file"),
_("Specifies the name of a file that is automatically parsed before the main file."),
r'^[\w\.,-/]+$'
),
'PHP-date.timezone': (
_("PHP - date.timezone"),
_("Sets the default timezone used by all date/time functions "
"(Timezone string 'Europe/London')."),
r'^\w+/\w+$'
),
'PHP-default_socket_timeout': (
_("PHP - Default socket timeout"),
_("Number between 0 and 999."),
r'^[0-9]{1,3}$'
),
'PHP-display_errors': (
_("PHP - Display errors"),
_("determines whether errors should be printed to the screen as part of the output or "
"if they should be hidden from the user (On or Off)."),
r'^(On|Off|on|off)$'
),
'PHP-extension': (
_("PHP - Extension"),
r'^[^ ]+$'
),
'PHP-magic_quotes_gpc': (
_("PHP - Magic quotes GPC"),
_("Sets the magic_quotes state for GPC (Get/Post/Cookie) operations (On or Off) "
"<b>DEPRECATED as of PHP 5.3.0</b>."),
r'^(On|Off|on|off)$'
),
'PHP-magic_quotes_runtime': (
_("PHP - Magic quotes runtime"),
_("Functions that return data from any sort of external source will have quotes escaped "
"with a backslash (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>."),
r'^(On|Off|on|off)$'
),
'PHP-magic_quotes_sybase': (
_("PHP - Magic quotes sybase"),
_("Single-quote is escaped with a single-quote instead of a backslash (On or Off)."),
r'^(On|Off|on|off)$'
),
'PHP-max_execution_time': (
_("PHP - Max execution time"),
_("Maximum time in seconds a script is allowed to run before it is terminated by "
"the parser (Integer between 0 and 999)."),
r'^[0-9]{1,3}$'
),
'PHP-max_input_time': (
_("PHP - Max input time"),
_("Maximum time in seconds a script is allowed to parse input data, like POST and GET "
"(Integer between 0 and 999)."),
r'^[0-9]{1,3}$'
),
'PHP-max_input_vars': (
_("PHP - Max input vars"),
_("How many input variables may be accepted (limit is applied to $_GET, $_POST and $_COOKIE superglobal separately) "
"(Integer between 0 and 9999)."),
r'^[0-9]{1,4}$'
),
'PHP-memory_limit': (
_("PHP - Memory limit"),
_("This sets the maximum amount of memory in bytes that a script is allowed to allocate "
"(Value between 0M and 999M)."),
r'^[0-9]{1,3}M$'
),
'PHP-mysql.connect_timeout': (
_("PHP - Mysql connect timeout"),
_("Number between 0 and 999."),
r'^([0-9]){1,3}$'
),
'PHP-output_buffering': (
_("PHP - output_buffering"),
_("Turn on output buffering (On or Off)."),
r'^(On|Off|on|off)$'
),
'PHP-register_globals': (
_("PHP - Register globals"),
_("Whether or not to register the EGPCS (Environment, GET, POST, Cookie, Server) "
"variables as global variables (On or Off)."),
r'^(On|Off|on|off)$'
),
'PHP-post_max_size': (
_("PHP - Post max size"),
_("Sets max size of post data allowed (Value between 0M and 999M)."),
r'^[0-9]{1,3}M$'
),
'PHP-sendmail_path': (
_("PHP - sendmail_path"),
_("Where the sendmail program can be found."),
r'^[^ ]+$'
),
'PHP-session.bug_compat_warn': (
_("PHP - session.bug_compat_warn"),
_("Enables an PHP bug on session initialization for legacy behaviour (On or Off)."),
r'^(On|Off|on|off)$'
),
'PHP-session.auto_start': (
_("PHP - session.auto_start"),
_("Specifies whether the session module starts a session automatically on request "
"startup (On or Off)."),
r'^(On|Off|on|off)$'
),
'PHP-safe_mode': (
_("PHP - Safe mode"),
_("Whether to enable PHP's safe mode (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>"),
r'^(On|Off|on|off)$'
),
'PHP-suhosin.post.max_vars': (
_("PHP - Suhosin POST max vars"),
_("Number between 0 and 9999."),
r'^[0-9]{1,4}$'
),
'PHP-suhosin.get.max_vars': (
_("PHP - Suhosin GET max vars"),
_("Number between 0 and 9999."),
r'^[0-9]{1,4}$'
),
'PHP-suhosin.request.max_vars': (
_("PHP - Suhosin request max vars"),
_("Number between 0 and 9999."),
r'^[0-9]{1,4}$'
),
'PHP-suhosin.session.encrypt': (
_("PHP - suhosin.session.encrypt"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-suhosin.simulation': (
_("PHP - Suhosin simulation"),
_("On or Off"),
r'^(On|Off|on|off)$'
),
'PHP-suhosin.executor.include.whitelist': (
_("PHP - suhosin.executor.include.whitelist"),
r'.*$'
),
'PHP-upload_max_filesize': (
_("PHP - upload_max_filesize"),
_("Value between 0M and 999M."),
r'^[0-9]{1,3}M$'
),
'PHP-zend_extension': (
_("PHP - zend_extension"),
r'^[^ ]+$'
),
})
WEBAPPS_ENABLED_OPTIONS = getattr(settings, 'WEBAPPS_ENABLED_OPTIONS', (
'orchestra.apps.webapps.options.public_root',
'orchestra.apps.webapps.options.timeout',
'orchestra.apps.webapps.options.processes',
'orchestra.apps.webapps.options.php_enabled_functions',
'orchestra.apps.webapps.options.php_allow_url_include',
'orchestra.apps.webapps.options.php_allow_url_fopen',
'orchestra.apps.webapps.options.php_auto_append_file',
'orchestra.apps.webapps.options.php_auto_prepend_file',
'orchestra.apps.webapps.options.php_date_timezone',
'orchestra.apps.webapps.options.php_default_socket_timeout',
'orchestra.apps.webapps.options.php_display_errors',
'orchestra.apps.webapps.options.php_extension',
'orchestra.apps.webapps.options.php_magic_quotes_gpc',
'orchestra.apps.webapps.options.php_magic_quotes_runtime',
'orchestra.apps.webapps.options.php_magic_quotes_sybase',
'orchestra.apps.webapps.options.php_max_execution_time',
'orchestra.apps.webapps.options.php_max_input_time',
'orchestra.apps.webapps.options.php_max_input_vars',
'orchestra.apps.webapps.options.php_memory_limit',
'orchestra.apps.webapps.options.php_mysql_connect_timeout',
'orchestra.apps.webapps.options.php_output_buffering',
'orchestra.apps.webapps.options.php_register_globals',
'orchestra.apps.webapps.options.php_post_max_size',
'orchestra.apps.webapps.options.php_sendmail_path',
'orchestra.apps.webapps.options.php_session_bug_compat_warn',
'orchestra.apps.webapps.options.php_session_auto_start',
'orchestra.apps.webapps.options.php_safe_mode',
'orchestra.apps.webapps.options.php_suhosin_post_max_vars',
'orchestra.apps.webapps.options.php_suhosin_get_max_vars',
'orchestra.apps.webapps.options.php_suhosin_request_max_vars',
'orchestra.apps.webapps.options.php_suhosin_session_encrypt',
'orchestra.apps.webapps.options.php_suhosin_simulation',
'orchestra.apps.webapps.options.php_suhosin_executor_include_whitelist',
'orchestra.apps.webapps.options.php_upload_max_filesize',
'orchestra.apps.webapps.options.php_zend_extension',
))
WEBAPPS_WORDPRESSMU_ADMIN_PASSWORD = getattr(settings, 'WEBAPPS_WORDPRESSMU_ADMIN_PASSWORD',
@ -332,3 +130,7 @@ WEBAPPS_DOKUWIKIMU_FARM_PATH = getattr(settings, 'WEBAPPS_DOKUWIKIMU_FARM_PATH',
WEBAPPS_DRUPAL_SITES_PATH = getattr(settings, 'WEBAPPS_DRUPAL_SITES_PATH',
'/home/httpd/htdocs/drupal-mu/sites/%(site_name)s')
WEBAPPS_DEFAULT_MYSQL_DATABASE_HOST = getattr(settings, 'WEBAPPS_DEFAULT_MYSQL_DATABASE_HOST',
'mysql.orchestra.lan')

View File

@ -0,0 +1,309 @@
from django import forms
from django.core.exceptions import ValidationError
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from orchestra import plugins
from orchestra.plugins.forms import PluginDataForm
from orchestra.core import validators
from orchestra.forms import widgets
from orchestra.utils.functional import cached
from orchestra.utils.python import import_class
from . import options, settings
class AppType(plugins.Plugin):
name = None
verbose_name = ""
help_text= ""
form = PluginDataForm
change_form = None
serializer = None
icon = 'orchestra/icons/apps.png'
unique_name = False
options = (
('Process', options.process),
('PHP', options.php),
('File system', options.filesystem),
)
@classmethod
@cached
def get_plugins(cls):
plugins = []
for cls in settings.WEBAPPS_TYPES:
plugins.append(import_class(cls))
return plugins
@classmethod
def clean_data(cls, webapp):
""" model clean, uses cls.serizlier by default """
if cls.serializer:
serializer = cls.serializer(data=webapp.data)
if not serializer.is_valid():
raise ValidationError(serializer.errors)
return serializer.data
return {}
def get_form(self):
self.form.plugin = self
self.form.plugin_field = 'type'
return self.form
def get_change_form(self):
form = self.change_form or self.form
form.plugin = self
form.plugin_field = 'type'
return form
def get_serializer(self):
self.serializer.plugin = self
return self.serializer
def validate(self, instance):
""" Unique name validation """
if self.unique_name:
if not instance.pk and Webapp.objects.filter(name=instance.name, type=instance.type).exists():
raise ValidationError({
'name': _("A WordPress blog with this name already exists."),
})
def get_options(self):
pass
@classmethod
def get_options_choices(cls):
enabled = options.get_enabled().values()
yield (None, '-------')
for option in cls.options:
if hasattr(option, '__iter__'):
yield (option[0], [(op.name, op.verbose_name) for op in option[1] if op in enabled])
elif option in enabled:
yield (option.name, option.verbose_name)
def save(self, instance):
pass
def delete(self, instance):
pass
def get_related_objects(self, instance):
pass
class Php55App(AppType):
name = 'php5.5-fpm'
verbose_name = "PHP 5.5 FPM"
# 'fpm', ('unix:/var/run/%(user)s-%(app_name)s.sock|fcgi://127.0.0.1%(app_path)s',),
directive = ('fpm', 'fcgi://{}%(app_path)s'.format(settings.WEBAPPS_FPM_LISTEN))
help_text = _("This creates a PHP5.5 application under ~/webapps/&lt;app_name&gt;<br>"
"PHP-FPM will be used to execute PHP files.")
options = (
('Process', options.process),
('PHP', [op for op in options.php if getattr(op, 'deprecated', 99) > 5.5]),
('File system', options.filesystem),
)
icon = 'orchestra/icons/apps/PHPFPM.png'
class Php52App(AppType):
name = 'php5.2-fcgi'
verbose_name = "PHP 5.2 FCGI"
directive = ('fcgi', settings.WEBAPPS_FCGID_PATH)
help_text = _("This creates a PHP5.2 application under ~/webapps/&lt;app_name&gt;<br>"
"Apache-mod-fcgid will be used to execute PHP files.")
icon = 'orchestra/icons/apps/PHPFCGI.png'
class Php4App(AppType):
name = 'php4-fcgi'
verbose_name = "PHP 4 FCGI"
directive = ('fcgi', settings.WEBAPPS_FCGID_PATH)
help_text = _("This creates a PHP4 application under ~/webapps/&lt;app_name&gt;<br>"
"Apache-mod-fcgid will be used to execute PHP files.")
icon = 'orchestra/icons/apps/PHPFCGI.png'
class StaticApp(AppType):
name = 'static'
verbose_name = "Static"
directive = ('static',)
help_text = _("This creates a Static application under ~/webapps/&lt;app_name&gt;<br>"
"Apache2 will be used to serve static content and execute CGI files.")
icon = 'orchestra/icons/apps/Static.png'
options = (
('File system', options.filesystem),
)
class WebalizerApp(AppType):
name = 'webalizer'
verbose_name = "Webalizer"
directive = ('static', '%(app_path)s%(site_name)s')
help_text = _("This creates a Webalizer application under "
"~/webapps/&lt;app_name&gt;-&lt;site_name&gt;")
icon = 'orchestra/icons/apps/Stats.png'
options = ()
class WordPressMuApp(AppType):
name = 'wordpress-mu'
verbose_name = "WordPress (SaaS)"
directive = ('fpm', 'fcgi://127.0.0.1:8990/home/httpd/wordpress-mu/')
help_text = _("This creates a WordPress site on a multi-tenant WordPress server.<br>"
"By default this blog is accessible via &lt;app_name&gt;.blogs.orchestra.lan")
icon = 'orchestra/icons/apps/WordPressMu.png'
unique_name = True
options = ()
class DokuWikiMuApp(AppType):
name = 'dokuwiki-mu'
verbose_name = "DokuWiki (SaaS)"
directive = ('alias', '/home/httpd/wikifarm/farm/')
help_text = _("This create a DokuWiki wiki into a shared DokuWiki server.<br>"
"By default this wiki is accessible via &lt;app_name&gt;.wikis.orchestra.lan")
icon = 'orchestra/icons/apps/DokuWikiMu.png'
unique_name = True
options = ()
class MoodleMuApp(AppType):
name = 'moodle-mu'
verbose_name = "Moodle (SaaS)"
directive = ('alias', '/home/httpd/wikifarm/farm/')
help_text = _("This create a Moodle site into a shared Moodle server.<br>"
"By default this wiki is accessible via &lt;app_name&gt;.moodle.orchestra.lan")
icon = 'orchestra/icons/apps/MoodleMu.png'
unique_name = True
options = ()
class DrupalMuApp(AppType):
name = 'drupal-mu'
verbose_name = "Drupdal (SaaS)"
directive = ('fpm', 'fcgi://127.0.0.1:8991/home/httpd/drupal-mu/')
help_text = _("This creates a Drupal site into a multi-tenant Drupal server.<br>"
"The installation will be completed after visiting "
"http://&lt;app_name&gt;.drupal.orchestra.lan/install.php?profile=standard<br>"
"By default this site will be accessible via &lt;app_name&gt;.drupal.orchestra.lan")
icon = 'orchestra/icons/apps/DrupalMu.png'
unique_name = True
options = ()
from rest_framework import serializers
from orchestra.forms import widgets
class SymbolicLinkForm(PluginDataForm):
path = forms.CharField(label=_("Path"), widget=forms.TextInput(attrs={'size':'100'}),
help_text=_("Path for the origin of the symbolic link."))
class SymbolicLinkSerializer(serializers.Serializer):
path = serializers.CharField(label=_("Path"))
class SymbolicLinkApp(AppType):
name = 'symbolic-link'
verbose_name = "Symbolic link"
form = SymbolicLinkForm
serializer = SymbolicLinkSerializer
icon = 'orchestra/icons/apps/SymbolicLink.png'
change_readonly_fileds = ('path',)
class WordPressForm(PluginDataForm):
db_name = forms.CharField(label=_("Database name"),
help_text=_("Database used for this webapp."))
db_user = forms.CharField(label=_("Database user"),)
db_pass = forms.CharField(label=_("Database user password"),
help_text=_("Initial database password."))
class WordPressSerializer(serializers.Serializer):
db_name = serializers.CharField(label=_("Database name"), required=False)
db_user = serializers.CharField(label=_("Database user"), required=False)
db_pass = serializers.CharField(label=_("Database user password"), required=False)
from orchestra.apps.databases.models import Database, DatabaseUser
from orchestra.utils.python import random_ascii
class WordPressApp(AppType):
name = 'wordpress'
verbose_name = "WordPress"
icon = 'orchestra/icons/apps/WordPress.png'
change_form = WordPressForm
serializer = WordPressSerializer
change_readonly_fileds = ('db_name', 'db_user', 'db_pass',)
help_text = _("Visit http://&lt;domain.lan&gt;/wp-admin/install.php to finish the installation.")
def get_db_name(self, webapp):
db_name = 'wp_%s_%s' % (webapp.name, webapp.account)
# Limit for mysql database names
return db_name[:65]
def get_db_user(self, webapp):
db_name = self.get_db_name(webapp)
# Limit for mysql user names
return db_name[:17]
def get_db_pass(self):
return random_ascii(10)
def validate(self, webapp):
create = not webapp.pk
if create:
db = Database(name=self.get_db_name(webapp), account=webapp.account)
user = DatabaseUser(username=self.get_db_user(webapp), password=self.get_db_pass(),
account=webapp.account)
for obj in (db, user):
try:
obj.full_clean()
except ValidationError, e:
raise ValidationError({
'name': e.messages,
})
def save(self, webapp):
create = not webapp.pk
if create:
db_name = self.get_db_name(webapp)
db_user = self.get_db_user(webapp)
db_pass = self.get_db_pass()
db = Database.objects.create(name=db_name, account=webapp.account)
user = DatabaseUser(username=db_user, account=webapp.account)
user.set_password(db_pass)
user.save()
db.users.add(user)
webapp.data = {
'db_name': db_name,
'db_user': db_user,
'db_pass': db_pass,
}
else:
# Trigger related backends
for related in self.get_related(webapp):
related.save()
def delete(self, webapp):
for related in self.get_related(webapp):
related.delete()
def get_related(self, webapp):
related = []
try:
db_user = DatabaseUser.objects.get(username=webapp.data.get('db_user'))
except DatabaseUser.DoesNotExist:
pass
else:
related.append(db_user)
try:
db = Database.objects.get(name=webapp.data.get('db_name'))
except Database.DoesNotExist:
pass
else:
related.append(db)
return related

View File

@ -10,7 +10,7 @@ from orchestra.admin.utils import admin_link, change_url
from orchestra.apps.accounts.admin import AccountAdminMixin, SelectAccountAdminMixin
from orchestra.forms.widgets import DynamicHelpTextSelect
from . import settings
from . import settings, options
from .forms import WebsiteAdminForm
from .models import Content, Website, WebsiteOption
@ -20,8 +20,7 @@ class WebsiteOptionInline(admin.TabularInline):
extra = 1
OPTIONS_HELP_TEXT = {
k: str(unicode(v[1])) if len(v) == 3 else ''
for k, v in settings.WEBSITES_OPTIONS.iteritems()
op.name: str(unicode(op.help_text)) for op in options.get_enabled().values()
}
# class Media:

View File

@ -5,10 +5,9 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _
from orchestra.core import validators, services
from orchestra.utils import tuple_setting_to_choices
from orchestra.utils.functional import cached
from . import settings
from . import settings, options
class Website(models.Model):
@ -78,15 +77,16 @@ class Website(models.Model):
path = settings.WEBSITES_WEBSITE_WWW_ERROR_LOG_PATH % context
return path.replace('//', '/')
class WebsiteOption(models.Model):
website = models.ForeignKey(Website, verbose_name=_("web site"),
related_name='options')
name = models.CharField(_("name"), max_length=128,
choices=tuple_setting_to_choices(settings.WEBSITES_OPTIONS))
choices=((op.name, op.verbose_name) for op in options.get_enabled().values()))
value = models.CharField(_("value"), max_length=256)
class Meta:
unique_together = ('website', 'name')
# unique_together = ('website', 'name')
verbose_name = _("option")
verbose_name_plural = _("options")
@ -94,16 +94,8 @@ class WebsiteOption(models.Model):
return self.name
def clean(self):
""" validates name and value according to WEBSITES_WEBSITEOPTIONS """
regex = settings.WEBSITES_OPTIONS[self.name][-1]
if not re.match(regex, self.value):
raise ValidationError({
'value': ValidationError(_("'%(value)s' does not match %(regex)s."),
params={
'value': self.value,
'regex': regex
}),
})
option = options.get_enabled()[self.name]
option.validate(self)
class Content(models.Model):

View File

@ -0,0 +1,127 @@
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from orchestra.utils.python import import_class
from . import settings
# TODO multiple and unique validation support in the formset
class SiteOption(object):
unique = True
def __init__(self, name, *args, **kwargs):
self.name = name
self.verbose_name = kwargs.pop('verbose_name', name)
self.help_text = kwargs.pop('help_text', '')
for k,v in kwargs.iteritems():
setattr(self, k, v)
def validate(self, website):
if self.regex and not re.match(self.regex, website.value):
raise ValidationError({
'value': ValidationError(_("'%(value)s' does not match %(regex)s."),
params={
'value': website.value,
'regex': self.regex
}),
})
directory_protection = SiteOption('directory_protection',
verbose_name=_("Directory protection"),
help_text=_("Space separated ..."),
regex=r'^([\w/_]+)\s+(\".*\")\s+([\w/_\.]+)$',
)
redirect = SiteOption('redirect',
verbose_name=_("Redirection"),
help_text=_("<tt>&lt;website path&gt; &lt;destination URL&gt;</tt>"),
regex=r'^[^ ]+\s[^ ]+$',
)
proxy = SiteOption('proxy',
verbose_name=_("Proxy"),
help_text=_("<tt>&lt;website path&gt; &lt;target URL&gt;</tt>"),
regex=r'^[^ ]+\shttp[^ ]+(timeout=[0-9]{1,3}|retry=[0-9]|\s)*$',
)
ssl_ca = SiteOption('ssl_ca',
verbose_name=_("SSL CA"),
help_text=_("Filesystem path of the CA certificate file."),
regex=r'^[^ ]+$'
)
ssl_cert = SiteOption('ssl_cert',
verbose_name=_("SSL cert"),
help_text=_("Filesystem path of the certificate file."),
regex=r'^[^ ]+$',
)
ssl_key = SiteOption('ssl_key',
verbose_name=_("SSL key"),
help_text=_("Filesystem path of the key file."),
regex=r'^[^ ]+$',
)
sec_rule_remove = SiteOption('sec_rule_remove',
verbose_name=_("SecRuleRemoveById"),
help_text=_("Space separated ModSecurity rule IDs."),
regex=r'^[0-9\s]+$',
)
sec_engine = SiteOption('sec_engine',
verbose_name=_("Modsecurity engine"),
help_text=_("<tt>On</tt> or <tt>Off</tt>, defaults to On"),
regex=r'^(On|Off)$',
)
user_group = SiteOption('user_group',
verbose_name=_("SuexecUserGroup"),
help_text=_("<tt>user [group]</tt>, username and optional groupname."),
# TODO validate existing user/group
regex=r'^[\w/_]+(\s[\w/_]+)*$',
)
error_document = SiteOption('error_document',
verbose_name=_("ErrorDocumentRoot"),
help_text=_("&lt;error code&gt; &lt;URL/path/message&gt;<br>"
"<tt>&nbsp;500 http://foo.example.com/cgi-bin/tester</tt><br>"
"<tt>&nbsp;404 /cgi-bin/bad_urls.pl</tt><br>"
"<tt>&nbsp;401 /subscription_info.html</tt><br>"
"<tt>&nbsp;403 \"Sorry can't allow you access today\"</tt>"),
regex=r'[45]0[0-9]\s.*',
)
ssl = [
ssl_ca,
ssl_cert,
ssl_key,
]
sec = [
sec_rule_remove,
sec_engine,
]
httpd = [
directory_protection,
redirect,
proxy,
user_group,
error_document,
]
_enabled = None
def get_enabled():
global _enabled
if _enabled is None:
from . import settings
_enabled = {}
for op in settings.WEBSITES_ENABLED_OPTIONS:
op = import_class(op)
_enabled[op.name] = op
return _enabled

View File

@ -6,12 +6,20 @@ WEBSITES_UNIQUE_NAME_FORMAT = getattr(settings, 'WEBSITES_UNIQUE_NAME_FORMAT',
'%(account)s-%(name)s')
# TODO 'http', 'https', 'https-only', 'http and https' and rename to PROTOCOL
WEBSITES_PORT_CHOICES = getattr(settings, 'WEBSITES_PORT_CHOICES', (
(80, 'HTTP'),
(443, 'HTTPS'),
))
WEBSITES_PROTOCOL_CHOICES = getattr(settings, 'WEBSITES_PROTOCOL_CHOICES', (
('http', 'HTTP'),
('https', 'HTTPS'),
('http-https', 'HTTP and HTTPS),
('https-only', 'HTTPS only'),
))
WEBSITES_DEFAULT_PORT = getattr(settings, 'WEBSITES_DEFAULT_PORT', 80)
@ -21,65 +29,18 @@ WEBSITES_DEFAULT_IP = getattr(settings, 'WEBSITES_DEFAULT_IP', '*')
WEBSITES_DOMAIN_MODEL = getattr(settings, 'WEBSITES_DOMAIN_MODEL', 'domains.Domain')
WEBSITES_OPTIONS = getattr(settings, 'WEBSITES_OPTIONS', {
# { name: ( verbose_name, [help_text], validation_regex ) }
'directory_protection': (
_("HTTPD - Directory protection"),
_("Space separated ..."),
r'^([\w/_]+)\s+(\".*\")\s+([\w/_\.]+)$',
),
'redirect': (
_("HTTPD - Redirection"),
_("<tt>&lt;website path&gt; &lt;destination URL&gt;</tt>"),
r'^[^ ]+\s[^ ]+$',
),
'proxy': (
_("HTTPD - Proxy"),
_("<tt>&lt;website path&gt; &lt;target URL&gt;</tt>"),
r'^[^ ]+\shttp[^ ]+(timeout=[0-9]{1,3}|retry=[0-9]|\s)*$',
),
'ssl_ca': (
"HTTPD - SSL CA",
_("Filesystem path of the CA certificate file."),
r'^[^ ]+$'
),
'ssl_cert': (
_("HTTPD - SSL cert"),
_("Filesystem path of the certificate file."),
r'^[^ ]+$'
),
'ssl_key': (
_("HTTPD - SSL key"),
_("Filesystem path of the key file."),
r'^[^ ]+$',
),
'sec_rule_remove': (
"HTTPD - SecRuleRemoveById",
_("Space separated ModSecurity rule IDs."),
r'^[0-9\s]+$',
),
'sec_engine': (
"HTTPD - Modsecurity engine",
_("<tt>On</tt> or <tt>Off</tt>, defaults to On"),
r'^(On|Off)$',
),
'user_group': (
"HTTPD - SuexecUserGroup",
_("<tt>user [group]</tt>, username and optional groupname."),
# TODO validate existing user/group
r'^[\w/_]+(\s[\w/_]+)*$',
),
# TODO backend support
'error_document': (
"HTTPD - ErrorDocumentRoot",
_("&lt;error code&gt; &lt;URL/path/message&gt;<br>"
"<tt>&nbsp;500 http://foo.example.com/cgi-bin/tester</tt><br>"
"<tt>&nbsp;404 /cgi-bin/bad_urls.pl</tt><br>"
"<tt>&nbsp;401 /subscription_info.html</tt><br>"
"<tt>&nbsp;403 \"Sorry can't allow you access today\"</tt>"),
r'[45]0[0-9]\s.*',
)
})
WEBSITES_ENABLED_OPTIONS = getattr(settings, 'WEBSITES_ENABLED_OPTIONS', (
'orchestra.apps.websites.options.directory_protection',
'orchestra.apps.websites.options.redirect',
'orchestra.apps.websites.options.proxy',
'orchestra.apps.websites.options.ssl_ca',
'orchestra.apps.websites.options.ssl_cert',
'orchestra.apps.websites.options.ssl_key',
'orchestra.apps.websites.options.sec_rule_remove',
'orchestra.apps.websites.options.sec_engine',
'orchestra.apps.websites.options.user_group',
'orchestra.apps.websites.options.error_document',
))
WEBSITES_BASE_APACHE_CONF = getattr(settings, 'WEBSITES_BASE_APACHE_CONF',

View File

@ -69,10 +69,11 @@ def paddingCheckboxSelectMultiple(padding):
class DynamicHelpTextSelect(forms.Select):
def __init__(self, target, help_text, *args, **kwargs):
help_text = self.get_dynamic_help_text(target, help_text)
attrs = {
attrs = kwargs.get('attrs', {})
attrs.update({
'onClick': help_text,
'onChange': help_text,
}
})
attrs.update(kwargs.get('attrs', {}))
kwargs['attrs'] = attrs
super(DynamicHelpTextSelect, self).__init__(*args, **kwargs)
@ -81,8 +82,8 @@ class DynamicHelpTextSelect(forms.Select):
return textwrap.dedent("""\
siteoptions = {help_text};
valueelement = $("#" + {target});
help_text = siteoptions[this.options[this.selectedIndex].value] || ""
valueelement.parent().find('p').remove();
valueelement.parent().append(
"<p class='help'>" + siteoptions[this.options[this.selectedIndex].value] + "</p>"
);""".format(target=target, help_text=str(help_text))
valueelement.parent().append("<p class='help'>" + help_text + "</p>");\
""".format(target=target, help_text=str(help_text))
)

View File

@ -1,7 +1,6 @@
from django.conf.urls import patterns, url
from django.contrib.admin.utils import unquote
from django.shortcuts import render, redirect
from django.utils.text import camel_case_to_spaces
from django.utils.translation import ugettext_lazy as _
from orchestra.admin.utils import wrap_admin_view
@ -11,14 +10,29 @@ from orchestra.utils.functional import cached
class SelectPluginAdminMixin(object):
plugin = None
plugin_field = None
plugin_title = None
def get_form(self, request, obj=None, **kwargs):
if obj:
self.form = getattr(obj, '%s_class' % self.plugin_field)().get_form()
plugin = getattr(obj, '%s_instance' % self.plugin_field)
self.form = getattr(plugin, 'get_change_form', plugin.get_form)()
else:
self.form = self.plugin.get_plugin(self.plugin_value)().get_form()
plugin = self.plugin.get_plugin(self.plugin_value)()
self.form = plugin.get_form()
return super(SelectPluginAdminMixin, self).get_form(request, obj=obj, **kwargs)
def get_fields(self, request, obj=None):
""" Try to maintain original field ordering """
fields = super(SelectPluginAdminMixin, self).get_fields(request, obj=obj)
head_fields = list(self.get_readonly_fields(request, obj))
head, tail = [], []
for field in fields:
if field in head_fields:
head.append(field)
else:
tail.append(field)
return head + tail
def get_urls(self):
""" Hooks select account url """
urls = super(SelectPluginAdminMixin, self).get_urls()
@ -34,6 +48,7 @@ class SelectPluginAdminMixin(object):
def select_plugin_view(self, request):
opts = self.model._meta
context = {
'plugin_title': self.plugin_title or 'Plugins',
'opts': opts,
'app_label': opts.app_label,
'field': self.plugin_field,
@ -52,8 +67,9 @@ class SelectPluginAdminMixin(object):
self.plugin_value = plugin_value
if not plugin_value:
self.plugin_value = self.plugin.get_plugins()[0].get_name()
plugin = self.plugin.get_plugin(self.plugin_value)
context = {
'title': _("Add new %s") % camel_case_to_spaces(self.plugin_value),
'title': _("Add new %s") % plugin.verbose_name,
}
context.update(extra_context or {})
return super(SelectPluginAdminMixin, self).add_view(request, form_url=form_url,
@ -62,9 +78,9 @@ class SelectPluginAdminMixin(object):
def change_view(self, request, object_id, form_url='', extra_context=None):
obj = self.get_object(request, unquote(object_id))
plugin_value = getattr(obj, self.plugin_field)
plugin = getattr(obj, '%s_class' % self.plugin_field)
context = {
'title': _("Change %s") % camel_case_to_spaces(str(plugin_value)),
'title': _("Change %s") % plugin.verbose_name,
}
context.update(extra_context or {})
return super(SelectPluginAdminMixin, self).change_view(request, object_id,

View File

@ -1,23 +1,32 @@
from django import forms
from orchestra.forms.widgets import ReadOnlyWidget
class PluginDataForm(forms.ModelForm):
data = forms.CharField(widget=forms.HiddenInput, required=False)
def __init__(self, *args, **kwargs):
super(PluginDataForm, self).__init__(*args, **kwargs)
# TODO remove it well
try:
self.fields[self.plugin_field].widget = forms.HiddenInput()
except KeyError:
pass
if self.plugin_field in self.fields:
value = self.plugin.get_name()
display = '%s <a href=".">change</a>' % unicode(self.plugin.verbose_name)
self.fields[self.plugin_field].widget = ReadOnlyWidget(value, display)
self.fields[self.plugin_field].help_text = getattr(self.plugin, 'help_text', '')
instance = kwargs.get('instance')
if instance:
for field in self.declared_fields:
initial = self.fields[field].initial
self.fields[field].initial = instance.data.get(field, initial)
if self.instance.pk:
for field in self.plugin.get_change_readonly_fileds():
value = getattr(self.instance, field, None) or self.instance.data[field]
self.fields[field].required = False
self.fields[field].widget = ReadOnlyWidget(value)
# self.fields[field].help_text = None
def clean(self):
# TODO clean all filed within data???
data = {}
for field in self.declared_fields:
try:

View File

@ -6,10 +6,11 @@ class Plugin(object):
# Used on select plugin view
class_verbose_name = None
icon = None
change_readonly_fileds = ()
@classmethod
def get_name(cls):
return cls.__name__
return getattr(cls, 'name', cls.__name__)
@classmethod
def get_plugins(cls):
@ -40,6 +41,10 @@ class Plugin(object):
choices.append((plugin.get_name(), verbose))
return sorted(choices, key=lambda e: e[1])
@classmethod
def get_change_readonly_fileds(cls):
return cls.change_readonly_fileds
class PluginModelAdapter(Plugin):
""" Adapter class for using model classes as plugins """

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -0,0 +1,630 @@
<?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"
id="svg3201"
version="1.1"
inkscape:version="0.48.3.1 r9886"
width="48"
height="48"
sodipodi:docname="DokuWikiMu.svg"
inkscape:export-filename="/home/glic3rinu/orchestra/django-orchestra/orchestra/static/orchestra/icons/apps/DokuWikiMu.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata
id="metadata3207">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3205">
<radialGradient
r="10.625"
fy="4.625"
fx="62.625"
cy="4.625"
cx="62.625"
gradientTransform="matrix(2.2657407,0,0,0.74122745,-117.89261,32.892968)"
gradientUnits="userSpaceOnUse"
id="radialGradient3610"
xlink:href="#linearGradient8838-7"
inkscape:collect="always" />
<linearGradient
id="linearGradient8838-7">
<stop
id="stop8840-0"
style="stop-color:black;stop-opacity:1"
offset="0" />
<stop
id="stop8842-7"
style="stop-color:black;stop-opacity:0"
offset="1" />
</linearGradient>
<radialGradient
r="10.625"
fy="4.625"
fx="62.625"
cy="4.625"
cx="62.625"
gradientTransform="matrix(2.2657407,0,0,0.74122745,-117.84341,35.950626)"
gradientUnits="userSpaceOnUse"
id="radialGradient3708"
xlink:href="#linearGradient8838-7"
inkscape:collect="always" />
<radialGradient
r="8.6813803"
fy="212.80016"
fx="224.41418"
cy="212.80016"
cx="224.41418"
gradientTransform="matrix(1,0,0,0.984179,0,3.366635)"
gradientUnits="userSpaceOnUse"
id="radialGradient2647"
xlink:href="#linearGradient2360"
inkscape:collect="always" />
<linearGradient
y2="189.01556"
x2="286.22665"
y1="189.01556"
x1="219.21262"
gradientUnits="userSpaceOnUse"
id="linearGradient2643"
xlink:href="#linearGradient2336"
inkscape:collect="always" />
<linearGradient
y2="192.73286"
x2="277.8761"
y1="192.73286"
x1="219.66267"
gradientUnits="userSpaceOnUse"
id="linearGradient2640"
xlink:href="#linearGradient2352"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="217.94008"
x2="255.68353"
y1="251.56442"
x1="275.71765"
id="linearGradient2630"
xlink:href="#linearGradient2624"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="213.12164"
x2="251.64362"
y1="234.52202"
x1="248.62152"
id="linearGradient2618"
xlink:href="#linearGradient2612"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="210.3558"
x2="206.06017"
y1="222.05145"
x1="202.41772"
id="linearGradient2606"
xlink:href="#linearGradient2600"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="307.52844"
x2="224.67441"
y1="241.52789"
x1="184.30582"
id="linearGradient2406"
xlink:href="#linearGradient2408"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="265.40363"
x2="244.79126"
y1="220.07191"
x1="213.96568"
id="linearGradient2395"
xlink:href="#linearGradient2389"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="172.32423"
x2="185.81258"
y1="262.28729"
x1="286.15598"
id="linearGradient2362"
xlink:href="#linearGradient2370"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="195.87151"
x2="136.14151"
y1="303.78967"
x1="140.15784"
id="linearGradient2354"
xlink:href="#linearGradient2348"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="289.50323"
x2="240.84924"
y1="184.99277"
x1="162.76369"
id="linearGradient2346"
xlink:href="#linearGradient2332"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="246.35907"
x2="201.40646"
y1="246.35907"
x1="184.07063"
id="linearGradient2325"
xlink:href="#linearGradient2360"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.631384,0,-173.4045)"
r="7.1440549"
fy="274.64203"
fx="257.41144"
cy="274.64203"
cx="257.41144"
id="radialGradient2317"
xlink:href="#linearGradient2360"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="258.91571"
x2="255.6561"
y1="258.91571"
x1="191.75092"
id="linearGradient2247"
xlink:href="#linearGradient2229"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="262.25757"
x2="263.67093"
y1="262.25757"
x1="192.03938"
id="linearGradient2227"
xlink:href="#linearGradient2249"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.984179,0,3.366635)"
r="8.6813803"
fy="212.80016"
fx="224.41418"
cy="212.80016"
cx="224.41418"
id="radialGradient2366"
xlink:href="#linearGradient2360"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="192.73286"
x2="277.8761"
y1="192.73286"
x1="219.66267"
id="linearGradient2350"
xlink:href="#linearGradient2352"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="189.01556"
x2="286.22665"
y1="189.01556"
x1="219.21262"
id="linearGradient2342"
xlink:href="#linearGradient2336"
inkscape:collect="always" />
<linearGradient
id="linearGradient2336">
<stop
id="stop2338"
offset="0"
style="stop-color:#8f2a15;stop-opacity:1;" />
<stop
id="stop2340"
offset="1"
style="stop-color:#c8381b;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2352">
<stop
style="stop-color:#ce411e;stop-opacity:1;"
offset="0"
id="stop2354" />
<stop
style="stop-color:#ecad8d;stop-opacity:1;"
offset="1"
id="stop2356" />
</linearGradient>
<linearGradient
id="linearGradient2360">
<stop
id="stop2362"
offset="0"
style="stop-color:#d69c00;stop-opacity:1;" />
<stop
id="stop2364"
offset="1"
style="stop-color:#ffe658;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2213">
<stop
id="stop2215"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop2217"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2229">
<stop
style="stop-color:#00b62b;stop-opacity:1;"
offset="0"
id="stop2231" />
<stop
style="stop-color:#a1d784;stop-opacity:1;"
offset="1"
id="stop2233" />
</linearGradient>
<linearGradient
id="linearGradient2249">
<stop
id="stop2251"
offset="0"
style="stop-color:#00a423;stop-opacity:1;" />
<stop
id="stop2253"
offset="1"
style="stop-color:#00b427;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2332">
<stop
id="stop2334"
offset="0"
style="stop-color:#ede1ae;stop-opacity:1;" />
<stop
id="stop2336"
offset="1"
style="stop-color:#fefdfa;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2348">
<stop
id="stop2350"
offset="0"
style="stop-color:#fbf6f0;stop-opacity:1;" />
<stop
id="stop2352"
offset="1"
style="stop-color:#e9dac7;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2364">
<stop
style="stop-color:#fbf6f0;stop-opacity:1;"
offset="0"
id="stop2366" />
<stop
style="stop-color:#e9dac7;stop-opacity:1;"
offset="1"
id="stop2368" />
</linearGradient>
<linearGradient
id="linearGradient2370">
<stop
id="stop2372"
offset="0"
style="stop-color:#fbfaf9;stop-opacity:1;" />
<stop
id="stop2374"
offset="1"
style="stop-color:#e9dac7;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2389">
<stop
id="stop2391"
offset="0"
style="stop-color:#000000;stop-opacity:0.17346939;" />
<stop
id="stop2393"
offset="1"
style="stop-color:#c7cec2;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2408">
<stop
style="stop-color:#000000;stop-opacity:0.17346939;"
offset="0"
id="stop2410" />
<stop
style="stop-color:#c7cec2;stop-opacity:0;"
offset="1"
id="stop2412" />
</linearGradient>
<marker
style="overflow:visible"
id="Arrow2Lstart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Lstart">
<path
inkscape:connector-curvature="0"
transform="matrix(1.1,0,0,1.1,-5.5,0)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
id="path2571" />
</marker>
<marker
style="overflow:visible"
id="TriangleOutL"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8,0.8)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
id="path2488" />
</marker>
<linearGradient
id="linearGradient2600">
<stop
id="stop2602"
offset="0"
style="stop-color:#e32525;stop-opacity:0.81632656;" />
<stop
id="stop2604"
offset="1"
style="stop-color:#e32525;stop-opacity:0.5714286;" />
</linearGradient>
<linearGradient
id="linearGradient2612">
<stop
id="stop2614"
offset="0"
style="stop-color:#25901b;stop-opacity:0.83673471;" />
<stop
id="stop2616"
offset="1"
style="stop-color:#25901b;stop-opacity:0.37755102;" />
</linearGradient>
<linearGradient
id="linearGradient2624">
<stop
id="stop2626"
offset="0"
style="stop-color:#3a9030;stop-opacity:0.83673471;" />
<stop
id="stop2628"
offset="1"
style="stop-color:#3d9c32;stop-opacity:0.79591835;" />
</linearGradient>
<inkscape:perspective
id="perspective100"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 526.18109 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<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="namedview3203"
showgrid="false"
inkscape:zoom="7.7918606"
inkscape:cx="10.453259"
inkscape:cy="21.076505"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg3201" />
<path
inkscape:connector-curvature="0"
d="m 48.122094,39.37881 c 0,4.34954 -10.77808,7.87555 -24.0735,7.87555 -13.29542,0 -24.07349952,-3.52601 -24.07349952,-7.87555 0,-4.34955 10.77807952,-7.87556 24.07349952,-7.87556 13.29542,0 24.0735,3.52601 24.0735,7.87556 l 0,0 z"
id="path8836-9"
style="opacity:0.3;fill:url(#radialGradient3708);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999988;marker:none;visibility:visible;display:inline;overflow:visible" />
<rect
style="fill:#eeeeec;stroke:#eeeeec"
id="rect3747"
width="31.308554"
height="23.776344"
x="8.3035679"
y="14.241219"
ry="11.888172" />
<path
style="fill:#6184a3;fill-opacity:1"
d="M 10.280293,40.441739 C 7.2051807,40.132054 4.8722076,39.068741 2.8990174,37.077537 -0.40380286,33.744562 -1.1067297,27.727678 1.1759893,23.645792 2.1196585,21.958353 3.8188126,20.299386 5.4807087,19.442893 l 0.7741857,-0.398997 0.011288,-1.226069 c 0.030962,-3.362392 1.3554573,-7.041803 3.9025052,-9.4279835 3.920374,-3.6727721 9.689551,-4.5169172 14.625477,-2.139999 2.531395,1.2190062 4.768749,3.4149696 5.824881,5.7171185 0.134346,0.29285 0.276817,0.532455 0.316601,0.532455 0.0398,0 0.324958,-0.170005 0.633723,-0.377784 2.080065,-1.399785 5.000273,-1.351753 7.212027,0.118622 2.543639,1.691007 3.424188,5.866753 1.989066,8.518585 -0.156214,0.28865 -0.263577,0.537672 -0.238588,0.553375 0.02499,0.0157 0.483839,0.173171 1.019662,0.349919 2.556281,0.843228 4.816568,3.003772 5.753516,5.499618 0.314345,0.837357 0.611974,2.379683 0.611974,3.171291 0,0.28762 -0.07623,1.867577 -0.169403,2.401863 -0.631568,3.621676 -3.342607,6.461999 -7.126882,7.466739 l -0.926404,0.245964 -14.513874,0.01651 c -7.982628,0.0092 -14.687708,-7.4e-4 -14.900171,-0.02236 z M 31.462046,14.76551 c -20.974697,22.156329 -10.487349,11.078164 0,0 z"
id="path3726"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssscsssssssscsssssccscc" />
<g
transform="matrix(0.73043968,0,0,0.73043968,-109.25563,-166.72103)"
style="display:inline"
inkscape:label="paper"
id="layer3">
<g
transform="matrix(0.3463897,0,0,0.3463897,105.30454,185.54142)"
id="g1419">
<g
id="g2376">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="rect1422"
d="m 120.21543,196.43769 70.90655,-0.79226 -2.40261,109.05308 -71.71761,0.37344 3.21367,-108.63426 z"
style="fill:url(#linearGradient2354);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.7216621px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
transform="matrix(0.989976,-0.141236,0.201069,0.979577,0,0)" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="rect1425"
d="m 179.20033,182.08731 79.84173,-19.51687 26.61391,101.72428 -82.50312,21.58684 -23.95252,-103.79425 z"
style="fill:url(#linearGradient2362);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="rect1419"
d="m 159.01353,181.74387 85.58587,0.53396 0,110.47429 -84.53387,-2.5127 -1.052,-108.49555 z"
style="fill:url(#linearGradient2346);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00418305px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
transform="matrix(0.995676,-0.09289891,0.08102261,0.996712,0,0)" />
</g>
<path
inkscape:connector-curvature="0"
transform="matrix(0.995433,-0.09546066,0.09546066,0.995433,0,0)"
style="font-size:12.0000124px;font-style:normal;font-weight:normal;line-height:125%;fill:#6184a3;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans"
d="m 167.55116,214.00773 0,-20.1846 5.34962,0 0,2.37403 -2.48145,0 0,15.43654 2.48145,0 0,2.37403 -5.34962,0 m 7.34767,0 0,-20.1846 5.34961,0 0,2.37403 -2.48144,0 0,15.43654 2.48144,0 0,2.37403 -5.34961,0 m 7.36915,-20.1846 5.81153,0 c 1.31054,2e-5 2.30956,0.10028 2.99707,0.30078 0.92382,0.27216 1.71516,0.75555 2.37403,1.4502 0.65884,0.69468 1.16014,1.54689 1.50391,2.55664 0.34373,1.00262 0.51561,2.24155 0.51562,3.71681 -10e-6,1.29623 -0.16115,2.41342 -0.4834,3.35156 -0.39389,1.14584 -0.95607,2.07325 -1.68652,2.78223 -0.55145,0.53711 -1.29624,0.95606 -2.23438,1.25684 -0.70183,0.222 -1.63999,0.33301 -2.81446,0.33301 l -5.9834,0 0,-15.74807 m 3.17969,2.66407 0,10.43067 2.37402,0 c 0.88802,1e-5 1.52897,-0.0501 1.92286,-0.15039 0.51561,-0.1289 0.94172,-0.34732 1.27832,-0.65527 0.34374,-0.30794 0.62304,-0.81282 0.83789,-1.51465 0.21483,-0.70898 0.32226,-1.6722 0.32227,-2.88965 -1e-5,-1.21744 -0.10744,-2.15201 -0.32227,-2.80372 -0.21485,-0.65168 -0.51563,-1.16014 -0.90234,-1.52539 -0.38673,-0.36522 -0.87729,-0.61229 -1.47168,-0.74121 -0.44402,-0.10025 -1.31414,-0.15038 -2.61036,-0.15039 l -1.42871,0 m 14.96388,13.084 -3.75977,-15.74807 3.25489,0 2.37403,10.8174 2.87891,-10.8174 3.78125,0 2.76074,11.00002 2.417,-11.00002 3.20118,0 -3.82423,15.74807 -3.37305,0 -3.13672,-11.77345 -3.12598,11.77345 -3.44825,0 m 22.76272,-15.74807 0,20.1846 -5.34961,0 0,-2.37403 2.48145,0 0,-15.45803 -2.48145,0 0,-2.35254 5.34961,0 m 7.34767,0 0,20.1846 -5.34962,0 0,-2.37403 2.48145,0 0,-15.45803 -2.48145,0 0,-2.35254 5.34962,0"
id="text2382" />
<g
style="display:inline"
id="g2632">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="csssssccccccssssscc"
id="path2414"
d="m 174.75585,201.60224 c -6.04576,2.46667 -10.16789,4.4194 -12.88454,6.35064 -2.71665,1.93124 -3.19257,4.60007 -3.24631,6.26587 -0.0269,0.8329 0.0809,1.77774 0.63189,2.44014 0.55103,0.6624 1.80769,1.87421 2.75794,2.38558 1.90049,1.02274 7.5417,2.42901 10.51899,3.07308 11.90917,2.57627 26.80568,1.68117 26.80568,1.68117 1.69307,1.2452 2.83283,2.82434 3.269,4.26902 4.5766,-1.88674 11.81084,-6.58439 13.15657,-8.57706 -5.45142,-4.19955 -10.79692,-6.33346 -16.51317,-8.30847 -1.59867,-0.71918 -2.87956,-1.22649 -0.71773,2.55635 0.98506,2.47275 0.85786,5.05143 0.57176,7.41825 0,0 -16.52749,0.40678 -28.23838,-2.1266 -2.92772,-0.63334 -5.46627,-0.95523 -7.21875,-1.89832 -0.87624,-0.47154 -1.48296,-0.8208 -1.91578,-1.3411 -0.43282,-0.5203 -0.2196,-1.29055 -0.20128,-1.85858 0.0366,-1.13607 0.25336,-1.67063 2.86177,-3.52492 2.60841,-1.85429 5.65407,-3.36195 11.65936,-5.81211 -0.0877,-1.29125 -0.29025,-2.5059 -1.29702,-2.99294 z"
style="fill:url(#linearGradient2606);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker-end:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsssscccccssssc"
id="path2608"
d="m 269.62539,220.7482 c -1.43576,-0.13963 -2.58044,0.30288 -2.56084,1.50218 0.94391,0.85652 1.34942,2.43518 1.48562,3.14008 0.1362,0.7049 0.0359,1.21914 -0.48562,1.89004 -1.043,1.3418 -3.12498,1.56875 -6.5006,2.72063 -6.75124,2.30377 -16.89306,2.52561 -27.90689,3.84639 -22.02767,2.64157 -39.03164,3.76107 -39.03164,3.76107 1.98346,-4.64758 6.32828,-4.41197 6.34903,-8.20969 0.27376,-0.89755 -3.14597,-1.31638 -5.09943,-0.10731 -4.26694,3.70137 -7.59152,6.75353 -10.69418,10.51311 l 1.88795,3.08438 c 0,0 26.13006,-2.88973 48.19776,-5.5361 11.03385,-1.32318 20.95601,-1.99856 27.80968,-4.33728 3.42683,-1.16936 5.95975,-1.49022 7.6409,-3.51958 0.63172,-0.76256 1.35238,-3.04699 1.06804,-4.73369 -0.21951,-1.30213 -1.14979,-3.09774 -2.15978,-4.01423 z"
style="fill:url(#linearGradient2618);fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="csscccccsscc"
id="path2620"
d="m 254.36185,220.33948 c -6.84997,3.24198 -7.15311,8.60912 -5.95953,12.79884 1.19358,4.18972 5.26293,8.75677 9.32121,12.40608 8.11656,7.29861 12.06046,9.33163 12.06046,9.33163 -3.71515,-0.10342 -7.89887,-1.41174 -8.13315,0.49304 -0.9483,2.97582 11.49137,3.47486 17.43787,2.70205 -1.39456,-7.57836 -3.79323,-13.21546 -7.73151,-14.90312 -1.68464,-0.14804 0.31242,4.72441 0.76985,9.39604 0,0 -3.62454,-1.73122 -11.60519,-8.90762 -3.99032,-3.5882 -7.37386,-7.3421 -8.47319,-11.20099 -1.09933,-3.85889 0.0776,-6.1205 4.95082,-9.53176 0.92816,-0.99528 -1.28985,-2.45913 -2.63764,-2.58419 z"
style="fill:url(#linearGradient2630);fill-opacity:1;fill-rule:evenodd;stroke:none" />
</g>
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient2395);fill-opacity:1;stroke:none;display:inline"
d="m 213.96569,234.57806 2.18756,-14.42897 15.21982,6.08793 21.49387,29.94828 -20.40591,9.21832 -18.49534,-30.82556 z"
id="rect2386"
sodipodi:nodetypes="cccccc" />
<g
style="display:inline"
id="g2649">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc"
id="path1443"
d="m 232.55816,219.5295 -15.92827,0.32199 3.08809,-15.15716 12.84018,14.83517 z"
style="fill:url(#radialGradient2647);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc"
id="path1452"
d="m 221.60041,219.29315 -4.41205,0.0782 0.85429,-3.98263 3.55776,3.90445 z"
style="fill:#812310;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc"
id="rect1437"
d="m 269.44172,159.27421 0.098,8.91471 8.0581,8.72344 7.75906,0.7992 -52.80669,41.84092 -6.66532,-3.30696 -5.08243,-5.618 -1.08987,-5.91194 49.72911,-45.44137 z"
style="fill:url(#linearGradient2643);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="rect1446"
d="m 268.94766,168.32844 8.3426,8.82719 -51.1007,38.68262 -4.9197,-5.4436 47.6778,-42.06621 z"
style="fill:url(#linearGradient2640);fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path1440"
d="m 285.33776,177.73216 -8.16219,-0.86619 -7.7518,-8.67862 0.0132,-9.14293 8.36213,0.75209 7.18862,9.57682 0.35007,8.35883 z"
style="fill:#ffe965;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;display:inline" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path1449"
d="m 280.72049,168.46367 0.1644,4.05654 -3.81335,-0.71676 -2.87504,-3.18901 -0.28089,-3.53393 3.85447,-0.16637 2.95041,3.54953 z"
style="fill:#cb391c;fill-opacity:1;fill-rule:evenodd;stroke:none" />
</g>
<g
style="display:inline"
id="g2657">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc"
id="rect2397"
d="m 183.88617,256.82796 0.99991,-16.30721 17.2878,8.44012 26.05488,38.00946 -29.28095,-1.13363 -15.06164,-29.00874 z"
style="fill:url(#linearGradient2406);fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc"
id="rect2207"
d="m 200.90647,238.44836 -8.04601,15.77386 -7.05577,-13.57337 15.10178,-2.20049 z"
style="fill:url(#linearGradient2325);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1;display:inline" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc"
id="rect1328"
d="m 201.05389,238.55401 62.11704,24.91912 -7.88689,3.21429 -4.35152,9.30976 1.1716,9.96396 -59.31453,-31.72759 -0.49402,-7.36382 3.09592,-5.82826 5.6624,-2.48746 z"
style="fill:url(#linearGradient2227);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="rect2204"
d="m 255.27801,266.53504 7.9241,-3.04772 0.85337,10.24037 -3.9011,8.28983 -8.04601,3.77919 -1.341,-9.63083 4.51064,-9.63084 z"
style="fill:url(#radialGradient2317);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1;display:inline" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="rect2210"
d="m 195.7549,241.421 59.13059,24.7962 -4.5917,9.76614 -57.48995,-29.00967 2.95106,-5.55267 z"
style="fill:url(#linearGradient2247);fill-opacity:1;stroke:none;display:inline" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="rect2308"
d="m 255.02263,275.21029 2.08411,-4.1069 2.96459,-1.06995 0.69433,3.37197 -1.76759,3.85723 -3.15516,1.38315 -0.82028,-3.4355 z"
style="fill:#00b527;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc"
id="rect2327"
d="m 186.56849,241.00362 3.54963,-0.47312 -2.02297,3.53926 -1.52666,-3.06614 z"
style="fill:#258209;fill-opacity:1;stroke:none;display:inline" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,160 @@
<?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"
id="svg3201"
version="1.1"
inkscape:version="0.48.3.1 r9886"
width="48"
height="48"
sodipodi:docname="DrupalMu.svg"
inkscape:export-filename="/home/glic3rinu/orchestra/django-orchestra/orchestra/static/orchestra/icons/apps/DrupalMu.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata
id="metadata3207">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3205">
<radialGradient
r="10.625"
fy="4.625"
fx="62.625"
cy="4.625"
cx="62.625"
gradientTransform="matrix(2.2657407,0,0,0.74122745,-117.89261,32.892968)"
gradientUnits="userSpaceOnUse"
id="radialGradient3610"
xlink:href="#linearGradient8838-7"
inkscape:collect="always" />
<linearGradient
id="linearGradient8838-7">
<stop
id="stop8840-0"
style="stop-color:black;stop-opacity:1"
offset="0" />
<stop
id="stop8842-7"
style="stop-color:black;stop-opacity:0"
offset="1" />
</linearGradient>
<radialGradient
r="10.625"
fy="4.625"
fx="62.625"
cy="4.625"
cx="62.625"
gradientTransform="matrix(2.2657407,0,0,0.74122745,-117.84341,35.950626)"
gradientUnits="userSpaceOnUse"
id="radialGradient3708"
xlink:href="#linearGradient8838-7"
inkscape:collect="always" />
</defs>
<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="namedview3203"
showgrid="false"
inkscape:zoom="3.8959303"
inkscape:cx="0.68424809"
inkscape:cy="43.440013"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg3201" />
<path
inkscape:connector-curvature="0"
d="m 48.122094,39.37881 c 0,4.34954 -10.77808,7.87555 -24.0735,7.87555 -13.29542,0 -24.07349952,-3.52601 -24.07349952,-7.87555 0,-4.34955 10.77807952,-7.87556 24.07349952,-7.87556 13.29542,0 24.0735,3.52601 24.0735,7.87556 l 0,0 z"
id="path8836-9"
style="opacity:0.3;fill:url(#radialGradient3708);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999988;marker:none;visibility:visible;display:inline;overflow:visible" />
<rect
style="fill:#eeeeec;stroke:#eeeeec"
id="rect3747"
width="31.308554"
height="23.776344"
x="8.3035679"
y="14.241219"
ry="11.888172" />
<path
style="fill:#93c5e4;fill-opacity:1"
d="M 10.280293,40.441737 C 7.2051807,40.132052 4.8722076,39.06874 2.8990174,37.077535 -0.40380281,33.74456 -1.1067297,27.727676 1.1759893,23.645787 2.1196585,21.958348 3.8188126,20.299384 5.4807087,19.442889 l 0.7741857,-0.398994 0.011289,-1.226072 C 6.2971444,14.455434 7.6216401,10.77602 10.168688,8.3898403 14.089062,4.7170682 19.858239,3.8729229 24.794165,6.249841 c 2.531395,1.2190065 4.768749,3.4149697 5.824881,5.717118 0.134346,0.292851 0.276817,0.532457 0.316601,0.532457 0.0398,0 0.324958,-0.170005 0.633723,-0.377787 2.080065,-1.399783 5.000273,-1.351751 7.212027,0.118622 2.543639,1.69101 3.424188,5.866753 1.989066,8.518588 -0.156214,0.28865 -0.263577,0.53767 -0.238588,0.553375 0.02499,0.0157 0.483839,0.17317 1.019662,0.349919 2.556281,0.843227 4.816568,3.00377 5.753516,5.499616 0.314345,0.837359 0.611974,2.379682 0.611974,3.17129 0,0.28762 -0.07623,1.86758 -0.169403,2.401864 -0.631568,3.621676 -3.342607,6.462001 -7.126882,7.466741 l -0.926404,0.245964 -14.513874,0.01651 c -7.982628,0.0092 -14.687708,-9.84e-4 -14.900171,-0.02238 z"
id="path3726"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssscsssssssscsssssccs" />
<g
id="g3003"
transform="matrix(0.64828664,0,0,0.64828664,7.5527918,8.5331199)"
inkscape:transform-center-x="-1.0664281"
inkscape:transform-center-y="-3.7324978">
<path
inkscape:connector-curvature="0"
id="path6"
d="M 34.090098,9.1797034 C 31.767567,7.7335672 29.576496,7.1638982 27.385409,5.7178032 26.026937,4.7975404 24.142593,2.6064525 22.565038,0.72214222 22.25828,3.7458125 21.33801,4.9728263 20.286308,5.8492663 18.05144,7.6020962 16.649147,8.1279792 14.721005,9.1797034 13.099587,10.012281 4.2914557,15.27086 4.2914557,26.576856 c 0,11.305933 9.5092553,19.632018 20.0702633,19.632018 10.560964,0 19.719685,-7.668772 19.719685,-19.281495 0,-11.612658 -8.589013,-16.871239 -9.991306,-17.7476756 z"
style="fill:#00598e" />
<path
inkscape:connector-curvature="0"
id="path8"
d="m 30.530787,36.388028 c 0.701163,0 1.44609,0.0438 1.97197,0.394389 0.525883,0.350543 0.832613,1.139364 1.007874,1.577551 0.175326,0.438212 0,0.701153 -0.350524,0.87644 -0.306789,0.175265 -0.35059,0.08764 -0.65735,-0.482051 -0.306753,-0.569651 -0.569681,-1.139366 -2.103434,-1.139366 -1.533754,0 -2.015805,0.525853 -2.760753,1.139366 -0.744944,0.613515 -1.007869,0.832642 -1.270808,0.482051 -0.262941,-0.350587 -0.175315,-0.701169 0.306737,-1.139365 0.482055,-0.4382 1.270828,-1.139365 2.015808,-1.44609 0.744953,-0.306791 1.139366,-0.262925 1.84048,-0.262925 l 0,0 z"
style="fill:#ffffff" />
<path
inkscape:connector-curvature="0"
id="path10"
d="m 23.256403,41.383671 c 0.876441,0.701124 2.191068,1.270827 4.995651,1.270827 2.804586,0 4.776586,-0.78882 5.652982,-1.446142 0.394412,-0.306731 0.569698,-0.04382 0.613499,0.131465 0.04386,0.175314 0.131464,0.43824 -0.175262,0.744974 -0.219127,0.21912 -2.234927,1.62141 -4.601264,1.840515 -2.366381,0.219093 -5.565349,0.350557 -7.493509,-1.402279 -0.306727,-0.306772 -0.219064,-0.74497 0,-0.920281 0.219126,-0.175272 0.394411,-0.306735 0.657352,-0.306735 0.262941,0 0.219087,0 0.350551,0.08764 l 0,0 z"
style="fill:#ffffff" />
<path
inkscape:connector-curvature="0"
id="path12"
d="m 12.520122,38.053242 c 3.33044,-0.04387 3.943947,-0.613513 6.879994,-1.928148 15.863396,-7.099116 18.799442,-13.584698 19.369108,-15.074612 0.569699,-1.489957 1.402279,-3.900151 0.525882,-6.573243 -0.169228,-0.516053 -0.29251,-0.930415 -0.381545,-1.263793 C 36.805518,10.856247 34.712656,9.5700024 34.080346,9.1748343 31.801615,7.728743 29.566731,7.159029 27.375628,5.7129375 26.017185,4.8365024 24.132844,2.6016154 22.555289,0.71728498 22.2485,3.7409777 21.372104,5.0118054 20.276556,5.8444006 18.041664,7.5972796 16.639386,8.1231321 14.711225,9.1748343 13.089836,10.051274 4.2816978,15.266054 4.2816978,26.571983 c 0,3.609719 0.9695098,6.915694 2.6329705,9.743944 l 0.4345376,-0.01556 c 0.920247,0.832595 2.3663601,1.796678 5.1709161,1.752879 z"
style="fill:#0073ba" />
<path
inkscape:connector-curvature="0"
id="path14"
d="M 34.080346,9.1748343 C 31.801615,7.728743 29.566731,7.159029 27.375628,5.7129375 26.017185,4.8365024 24.132844,2.6016154 22.555289,0.71728498 22.2485,3.7409777 21.372104,5.0118054 20.276556,5.8444006 18.041664,7.5972796 16.639386,8.1231321 14.711225,9.1748343 13.089836,10.051274 4.2816978,15.266054 4.2816978,26.571983 c 0,3.609719 0.9695098,6.915694 2.6329705,9.743944 3.5466277,6.029889 10.2482267,9.888084 17.4372997,9.888084 10.560956,0 19.719684,-7.668772 19.719684,-19.281437 0,-6.377263 -2.590255,-10.837861 -5.158091,-13.709128 -2.108043,-2.357199 -4.201049,-3.6434436 -4.833215,-4.0386117 z m 5.326588,5.1298647 c 2.877156,3.597128 4.336061,7.842377 4.336061,12.617875 0,2.771148 -0.527811,5.388863 -1.568747,7.780659 -0.987459,2.26883 -2.4094,4.278898 -4.226366,5.974547 -3.591569,3.351706 -8.41997,5.197573 -13.595914,5.197573 -2.560687,0 -5.073487,-0.489081 -7.468591,-1.453807 -2.352527,-0.94753 -4.472551,-2.3043 -6.30115,-4.032752 -3.8510202,-3.639797 -5.9718669,-8.546757 -5.9718669,-13.816811 0,-4.693944 1.5235887,-8.864822 4.5283833,-12.396626 2.2956266,-2.698273 4.7710076,-4.1936671 5.7287516,-4.7113412 0.46499,-0.2536462 0.901182,-0.4774924 1.323031,-0.6939519 1.32225,-0.678689 2.571148,-1.3196827 4.288889,-2.6669881 0.915988,-0.6961406 1.891737,-1.7987311 2.307277,-4.5984547 1.447515,1.7216416 3.127255,3.6563963 4.410821,4.484523 1.139353,0.7519791 2.307987,1.2788589 3.438159,1.7885041 1.069149,0.482029 2.174638,0.9804706 3.268631,1.674732 0.0018,0.00136 0.04099,0.025553 0.04099,0.025553 3.197924,1.9966268 4.901719,4.1267468 5.461639,4.8267578 z"
style="fill:#004975" />
<path
inkscape:connector-curvature="0"
id="path16"
d="m 22.774381,1.5937182 c 0.613483,1.7966831 0.525884,2.7169311 0.525884,3.1113198 0,0.394389 -0.219126,1.4461034 -0.920295,1.9719862 -0.306733,0.2190788 -0.394395,0.3944051 -0.394395,0.4382036 0,0.1752646 0.394395,0.3067268 0.394395,0.7011334 0,0.4820332 -0.21907,1.4461351 -2.541615,3.7686668 -2.322573,2.322534 -5.653013,4.382137 -8.238475,5.652966 C 9.0144231,18.508823 7.7874103,18.421161 7.4368549,17.807679 7.0862773,17.194197 7.5683179,15.835704 9.1896923,14.039023 10.811103,12.242345 15.93822,9.6568851 15.93822,9.6568851 L 22.336162,5.1870844 22.68675,3.4780508"
style="fill:#93c5e4" />
<path
inkscape:connector-curvature="0"
id="path18"
d="m 22.774381,1.5498967 c -0.394411,2.8922154 -1.270807,3.7686495 -2.454025,4.6888929 -1.971942,1.4899534 -3.900084,2.4101952 -4.338323,2.6293198 -1.139337,0.56965 -5.258593,2.8483826 -7.4058104,6.1350136 -0.6573465,1.007866 0,1.402277 0.1314641,1.489895 0.131463,0.08765 1.6213643,0.262925 4.8203393,-1.665218 3.198971,-1.928143 4.601261,-3.067507 6.397943,-4.951807 0.964103,-1.0078836 1.095567,-1.5775986 1.095567,-1.8405239 0,-0.3067261 -0.219128,-0.4381895 -0.569719,-0.5258525 -0.175261,-0.043802 -0.219059,-0.1314622 0,-0.2629256 0.219128,-0.1314632 1.139369,-0.5696668 1.358493,-0.744977 0.219126,-0.1752639 1.270829,-0.8764349 1.314629,-2.0157916 0.04386,-1.1393393 -0.04381,-1.9281403 -0.350558,-2.9360257 l 0,0 z"
style="fill:#ffffff" />
<path
inkscape:connector-curvature="0"
id="path20"
d="m 12.914535,33.408116 c 0.04385,-3.418034 3.242809,-6.617006 7.274359,-6.660868 5.127116,-0.04381 8.676675,5.083317 11.26213,5.039515 2.191071,-0.04387 6.397946,-4.338339 8.457552,-4.338339 2.191088,0 2.804583,2.278733 2.804583,3.637161 0,1.358492 -0.438189,3.812486 -1.489891,5.346241 -1.051765,1.533753 -1.709079,2.103413 -2.936046,2.015805 -1.577616,-0.131461 -4.732726,-5.039515 -6.748531,-5.127114 -2.541658,-0.08765 -8.063164,5.302379 -12.4015,5.302379 -2.629275,0 -3.418098,-0.394389 -4.294495,-0.964053 -1.31467,-0.920292 -1.971987,-2.322573 -1.928161,-4.250727 l 0,0 z"
style="fill:#ffffff" />
<path
inkscape:connector-curvature="0"
id="path22"
d="m 39.295106,14.477239 c 0.876397,2.673092 0.04383,5.083286 -0.525882,6.573243 -0.569666,1.489914 -3.505712,7.975496 -19.369108,15.074612 -2.936047,1.314635 -3.549554,1.884286 -6.879994,1.928148 -2.804556,0.04381 -4.2506691,-0.920282 -5.1709161,-1.752877 l -0.4345376,0.01555 C 10.461296,42.345805 17.162895,46.204 24.351968,46.204 c 10.560956,0 19.719684,-7.668772 19.719684,-19.281438 0,-6.377263 -2.590255,-10.83786 -5.158091,-13.709127 0.08902,0.333378 0.212317,0.74774 0.381545,1.263793 z"
style="fill:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
width="300"
height="159"
viewBox="0 0 300 160"
id="svg2943">
<defs
id="defs2945">
<linearGradient
x1="150"
y1="84"
x2="299"
y2="84"
id="linearGradient3798"
gradientUnits="userSpaceOnUse">
<stop
id="stop3800"
style="stop-color:#dddce9;stop-opacity:1"
offset="0" />
<stop
id="stop3802"
style="stop-color:#5664a3;stop-opacity:1"
offset="0.37" />
<stop
id="stop3804"
style="stop-color:#000000;stop-opacity:1"
offset="1" />
</linearGradient>
<radialGradient
cx="77.914261"
cy="-48.544521"
r="146"
fx="77.914261"
fy="-48.544521"
id="radialGradient3870"
xlink:href="#linearGradient3798"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5089497,0,0,1.3582164,-39.028917,76.957747)" />
</defs>
<ellipse
cx="150"
cy="80"
rx="146"
ry="76"
id="ellipse3860"
style="fill:#6c7eb7;stroke:url(#radialGradient3870);stroke-width:5.5" />
<path
d="m 45,125 16,-81 37,0 c 16,1 24,9 24,23 0,24 -19,38 -36,37 l -18,0 -4,21 -19,0 z m 27,-36 5,-30 13,0 c 7,0 12,3 12,9 -1,17 -9,20 -18,21 l -12,0 z"
id="p"
style="fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linejoin:round" />
<path
d="m 116,104 16,-81 19,0 -4,21 18,0 c 16,1 22,9 20,19 l -7,41 -20,0 7,-37 c 1,-5 1,-8 -6,-8 l -15,0 -9,45 -19,0 z"
id="h"
style="stroke:#ffffff;stroke-width:2;stroke-linejoin:round" />
<use
transform="translate(134,0)"
id="p2"
xlink:href="#p" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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="48"
height="48"
viewBox="0 0 48 48.301887"
id="svg2943"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="PHPFCGI.svg"
inkscape:export-filename="/home/glic3rinu/orchestra/django-orchestra/orchestra/static/orchestra/icons/apps/PHPFCGI.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata
id="metadata15">
<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></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="namedview13"
showgrid="false"
inkscape:zoom="23.834212"
inkscape:cx="29.136432"
inkscape:cy="25.452333"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg2943" />
<defs
id="defs2945">
<linearGradient
x1="150"
y1="84"
x2="299"
y2="84"
id="linearGradient3798"
gradientUnits="userSpaceOnUse">
<stop
id="stop3800"
style="stop-color:#dddce9;stop-opacity:1"
offset="0" />
<stop
id="stop3802"
style="stop-color:#5664a3;stop-opacity:1"
offset="0.37" />
<stop
id="stop3804"
style="stop-color:#000000;stop-opacity:1"
offset="1" />
</linearGradient>
<radialGradient
cx="77.914261"
cy="-48.544521"
r="146"
fx="77.914261"
fy="-48.544521"
id="radialGradient3870"
xlink:href="#linearGradient3798"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5089497,0,0,1.3582164,-39.028917,76.957747)" />
<radialGradient
cx="77.914261"
cy="-48.544521"
r="146"
fx="77.914261"
fy="-48.544521"
id="radialGradient3870-6"
xlink:href="#linearGradient3798-8"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5089497,0,0,1.3582164,-39.028917,76.957747)" />
<linearGradient
x1="150"
y1="84"
x2="299"
y2="84"
id="linearGradient3798-8"
gradientUnits="userSpaceOnUse">
<stop
id="stop3800-0"
style="stop-color:#dddce9;stop-opacity:1"
offset="0" />
<stop
id="stop3802-9"
style="stop-color:#5664a3;stop-opacity:1"
offset="0.37" />
<stop
id="stop3804-4"
style="stop-color:#000000;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
inkscape:collect="always"
id="filter3797"
x="-0.13393395"
width="1.2678679"
y="-0.25729417"
height="1.5145883">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="16.295298"
id="feGaussianBlur3799" />
</filter>
</defs>
<ellipse
cx="150"
cy="80"
rx="146"
ry="76"
id="ellipse3860-0"
style="fill:#555753;fill-opacity:1;stroke:#555753;stroke-width:5.5;filter:url(#filter3797)"
sodipodi:cx="150"
sodipodi:cy="80"
sodipodi:rx="146"
sodipodi:ry="76"
transform="matrix(0.13546531,0,0,0.05031395,5.6817942,36.572954)" />
<ellipse
cx="150"
cy="80"
rx="146"
ry="76"
id="ellipse3860"
style="fill:#6c7eb7;stroke:url(#radialGradient3870);stroke-width:5.5"
sodipodi:cx="150"
sodipodi:cy="80"
sodipodi:rx="146"
sodipodi:ry="76"
transform="matrix(0.1620589,0,0,0.25666252,-0.33382188,2.2009827)" />
<path
d="m 5.4618682,23.497045 2.59294,-13.126772 5.9961898,0 c 2.59294,0.162059 3.889411,1.458533 3.889411,3.727358 0,3.889414 -3.07915,6.158237 -5.834128,5.996179 l -2.9170559,0 -0.6482379,3.403235 -3.079119,0 z m 4.3755911,-5.834117 0.8102927,-4.861768 2.106768,0 c 1.13439,0 1.944715,0.486177 1.944715,1.45853 -0.162094,2.755001 -1.458553,3.241178 -2.917071,3.403238 l -1.9447047,0 z"
id="p"
style="fill-rule:evenodd;stroke:#ffffff;stroke-width:0.32411811;stroke-linejoin:round"
inkscape:connector-curvature="0" />
<path
d="m 18.305109,20.09381 2.592939,-13.1267725 3.079118,0 -0.648239,3.4032355 2.917073,0 c 2.592954,0.162059 3.56531,1.458533 3.241193,3.079124 l -1.134446,6.644413 -3.241174,0 1.134427,-5.996179 c 0.162043,-0.810294 0.162043,-1.296471 -0.972356,-1.296471 l -2.430892,0 -1.45854,7.29265 -3.079103,0 z"
id="h"
style="stroke:#ffffff;stroke-width:0.32411811;stroke-linejoin:round"
inkscape:connector-curvature="0" />
<use
transform="translate(23.728448,-1.7015835e-7)"
id="p2"
xlink:href="#p"
x="0"
y="0"
width="300"
height="160" />
<text
xml:space="preserve"
style="font-size:14.08805083999999930px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:128.99999619000001871%;letter-spacing:-0.96603775000000003px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono Bold Italic;stroke-width:0.30188679;stroke-miterlimit:4;stroke-dasharray:none"
x="7.2367697"
y="35.194664"
id="text2992"
sodipodi:linespacing="129%"><tspan
sodipodi:role="line"
id="tspan2994"
x="7.2367697"
y="35.194664"
style="font-size:14.08805083999999930px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;letter-spacing:-0.96603775000000003px;stroke:#ffffff;stroke-width:0.30188679;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;font-family:OpenSymbol;-inkscape-font-specification:OpenSymbol Bold Italic">FCGI</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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="48"
height="48"
viewBox="0 0 48 48.301887"
id="svg2943"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="PHPFPM.svg"
inkscape:export-filename="/home/glic3rinu/orchestra/django-orchestra/orchestra/static/orchestra/icons/apps/PHPFPM.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata
id="metadata15">
<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></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="namedview13"
showgrid="false"
inkscape:zoom="8.4266665"
inkscape:cx="-4.8021953"
inkscape:cy="14.32354"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg2943" />
<defs
id="defs2945">
<linearGradient
x1="150"
y1="84"
x2="299"
y2="84"
id="linearGradient3798"
gradientUnits="userSpaceOnUse">
<stop
id="stop3800"
style="stop-color:#dddce9;stop-opacity:1"
offset="0" />
<stop
id="stop3802"
style="stop-color:#5664a3;stop-opacity:1"
offset="0.37" />
<stop
id="stop3804"
style="stop-color:#000000;stop-opacity:1"
offset="1" />
</linearGradient>
<radialGradient
cx="77.914261"
cy="-48.544521"
r="146"
fx="77.914261"
fy="-48.544521"
id="radialGradient3870"
xlink:href="#linearGradient3798"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5089497,0,0,1.3582164,-39.028917,76.957747)" />
<radialGradient
cx="77.914261"
cy="-48.544521"
r="146"
fx="77.914261"
fy="-48.544521"
id="radialGradient3870-6"
xlink:href="#linearGradient3798-8"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5089497,0,0,1.3582164,-39.028917,76.957747)" />
<linearGradient
x1="150"
y1="84"
x2="299"
y2="84"
id="linearGradient3798-8"
gradientUnits="userSpaceOnUse">
<stop
id="stop3800-0"
style="stop-color:#dddce9;stop-opacity:1"
offset="0" />
<stop
id="stop3802-9"
style="stop-color:#5664a3;stop-opacity:1"
offset="0.37" />
<stop
id="stop3804-4"
style="stop-color:#000000;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
inkscape:collect="always"
id="filter3797"
x="-0.13393395"
width="1.2678679"
y="-0.25729417"
height="1.5145883">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="16.295298"
id="feGaussianBlur3799" />
</filter>
</defs>
<ellipse
cx="150"
cy="80"
rx="146"
ry="76"
id="ellipse3860-0"
style="fill:#555753;fill-opacity:1;stroke:#555753;stroke-width:5.5;filter:url(#filter3797)"
sodipodi:cx="150"
sodipodi:cy="80"
sodipodi:rx="146"
sodipodi:ry="76"
transform="matrix(0.13546531,0,0,0.05031395,5.6817942,36.572954)" />
<ellipse
cx="150"
cy="80"
rx="146"
ry="76"
id="ellipse3860"
style="fill:#6c7eb7;stroke:url(#radialGradient3870);stroke-width:5.5"
sodipodi:cx="150"
sodipodi:cy="80"
sodipodi:rx="146"
sodipodi:ry="76"
transform="matrix(0.1620589,0,0,0.25666252,-0.33382188,2.2009827)" />
<path
d="m 5.4618682,23.497045 2.59294,-13.126772 5.9961898,0 c 2.59294,0.162059 3.889411,1.458533 3.889411,3.727358 0,3.889414 -3.07915,6.158237 -5.834128,5.996179 l -2.9170559,0 -0.6482379,3.403235 -3.079119,0 z m 4.3755911,-5.834117 0.8102927,-4.861768 2.106768,0 c 1.13439,0 1.944715,0.486177 1.944715,1.45853 -0.162094,2.755001 -1.458553,3.241178 -2.917071,3.403238 l -1.9447047,0 z"
id="p"
style="fill-rule:evenodd;stroke:#ffffff;stroke-width:0.32411811;stroke-linejoin:round"
inkscape:connector-curvature="0" />
<path
d="m 18.305109,20.09381 2.592939,-13.1267725 3.079118,0 -0.648239,3.4032355 2.917073,0 c 2.592954,0.162059 3.56531,1.458533 3.241193,3.079124 l -1.134446,6.644413 -3.241174,0 1.134427,-5.996179 c 0.162043,-0.810294 0.162043,-1.296471 -0.972356,-1.296471 l -2.430892,0 -1.45854,7.29265 -3.079103,0 z"
id="h"
style="stroke:#ffffff;stroke-width:0.32411811;stroke-linejoin:round"
inkscape:connector-curvature="0" />
<use
transform="translate(23.728448,-1.7015835e-7)"
id="p2"
xlink:href="#p"
x="0"
y="0"
width="300"
height="160" />
<text
xml:space="preserve"
style="font-size:14.08805084px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:128.99999619%;letter-spacing:-0.96603775px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono Bold Italic"
x="7.638485"
y="35.075245"
id="text2992"
sodipodi:linespacing="129%"><tspan
sodipodi:role="line"
id="tspan2994"
x="7.638485"
y="35.075245"
style="font-size:14.08805084px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;letter-spacing:-0.96603775px;stroke:#ffffff;stroke-width:0.3018868;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;font-family:OpenSymbol;-inkscape-font-specification:OpenSymbol Bold Italic">FPM</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -0,0 +1,36 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48">
<defs>
<linearGradient id="lg1">
<stop stop-color="#3778ae" offset="0"/>
<stop stop-color="#366c99" offset="1"/>
</linearGradient>
<linearGradient id="lg2">
<stop stop-color="#fff" offset="0"/>
<stop stop-color="#fff" stop-opacity="0.165" offset="1"/>
</linearGradient>
<linearGradient id="lg3">
<stop stop-color="#ffe253" offset="0"/>
<stop stop-color="#ffca1c" offset="1"/>
</linearGradient>
<linearGradient id="lg4">
<stop stop-color="#000" offset="0"/>
<stop stop-color="#000" stop-opacity="0" offset="1"/>
</linearGradient>
<linearGradient x1="94.693" y1="112.511" x2="94.693" y2="64.053" id="lg5" xlink:href="#lg2" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.353878,0,0,0.353878,-17.3795,-19.412)"/>
<linearGradient x1="59.728" y1="102" x2="142.62" y2="102" id="lg6" xlink:href="#lg1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.353878,0,0,0.353878,-17.3795,-19.412)"/>
<linearGradient x1="94.693" y1="112.511" x2="94.693" y2="64.053" id="lg7" xlink:href="#lg2" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.353878,0,0,0.353878,-6.29697,-7.94537)"/>
<linearGradient x1="119.191" y1="89.13" x2="116.965" y2="169.279" id="lg8" xlink:href="#lg3" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.353878,0,0,0.353878,-16.3897,-17.997)"/>
<radialGradient cx="15.115" cy="63.965" r="12.289" fx="15.115" fy="63.965" id="rg1" xlink:href="#lg4" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.6,0,0,0.551754,-0.183975,4.83575)"/>
</defs>
<path d="m 43.6618,40.1289 a 19.6618,6.7805 0 0 1 -39.3236,0 19.6618,6.7805 0 1 1 39.3236,0 z" fill="url(#rg1)"/>
<path d="m 34.0804,37.5795 c 0,2.7319 -2.371,4.1156 -4.7774,4.8057 -3.6202,1.0404 -6.5255,0.8811 -9.5511,0 -2.5268,-0.7362 -4.7774,-2.2402 -4.7774,-4.8057 l 0,-9.0132 c 0,-2.594 2.1621,-4.8092 4.7774,-4.8092 l 9.3984,-0.6111 c 3.1814,0 5.2606,-1.9858 5.2606,-5.245 l 0.8655,-4.3569 3.5813,0 c 2.7814,0 4.0909,2.0667 4.7774,4.8056 0.9555,3.8043 0.9978,6.6495 0,9.615 -0.9661,2.8805 -2,4.8056 -4.7774,4.8056 l -4.7773,0 -9.5512,0 0,-0.02 c 8.2424,0.02 9.5512,-3.3164 9.5512,4.8281 z" fill="url(#lg8)"/>
<path d="m 28.1104,38.1776 c 0,-0.9944 0.8033,-1.8013 1.7906,-1.8013 1,0 1.7906,0.8069 1.7906,1.8013 0,0.9979 -0.7997,1.8047 -1.7906,1.8047 -0.9873,0 -1.7906,-0.8068 -1.7906,-1.8047 z" fill="#fff"/>
<path d="m 35.2662,13.5436 0,4.2265 C 31.8551,23.767 25.375,23.7787 19.939,23.7787 l -2.017,0.2052 c -2.8342,2.4364 -2.9244,6.3463 -2.9223,9.7756 6.2502,-6.9742 12.9174,-7.5004 16.2436,-7.4854 6.6377,0.029 9.7638,-1.6029 12.9339,-5.1939 -0.016,-0.07 0.016,-0.132 0,-0.2037 -0.1222,-0.8 -0.3362,-1.6544 -0.5601,-2.546 -0.3218,-1.2839 -0.7428,-2.4141 -1.4257,-3.2589 -0.016,-0.016 -0.038,-0.034 -0.051,-0.05 0,0 -0.042,0 -0.05,0 -0.023,-0.028 -0.028,-0.075 -0.05,-0.1011 -0.047,-0.034 -0.052,-0.07 -0.101,-0.101 -0.016,-0.016 -0.039,0.016 -0.05,0 C 41.1653,14.3502 40.2858,14 39.3942,13.8519 38.5861,13.7183 37.775,13.6165 36.95,13.5464 l -0.5092,0 -1.1711,0 z" opacity="0.837" fill="url(#lg7)"/>
<path d="m 34.559,37.579 c 0,2.732 -2.8497,4.116 -5.256,4.806 -3.62,1.04 -6.525,0.881 -9.551,0 -2.527,-0.736 -4.801,-2.24 -4.805,-4.805 l -0.016,-9.258 c -0.01,-3.073 2.302,-5.01 4.849,-5 l 8.4667,0.015 c 3.25,0 6.41,-3.3 6.401,-6.55 l 0,-3.237 4.21,0 c 2.7814,0 4.09,2.067 4.777,4.806 0.956,3.804 1,6.649 0,9.615 -0.966,2.88 -2,5.1476 -4.777,5.148 l -4.3,0 -10.03,0 0,-0.02 10.03,0.034 z" fill="none" stroke="#bb9400" stroke-width="1.63"/>
<path d="m 35.4653,14.3584 0,2.3933 c 0,3.7245 -3.4965,7.3757 -7.4809,7.3757 l -8.2491,0 c -2.8506,0 -4.0184,2.1569 -4.0042,4.4379 l 0.056,9.0129 c 0.01,1.0446 0.4,1.8235 1.148,2.4951 0.748,0.6715 1.8726,1.183 3.0553,1.5277 2.9164,0.8492 5.576,1.0022 9.0638,0 1.1327,-0.3248 2.6394,-0.9401 3.3976,-1.5964 0.7581,-0.6565 1.3077,-1.2961 1.3077,-2.4264 l 0,-3.6298 -10.052,0 0,-1.6795 15.1743,0.05 c 1.2008,0 1.788,-0.4724 2.3844,-1.1633 0.5964,-0.691 1.1149,-2.0469 1.5874,-3.456 0.9456,-2.8096 0.9336,-5.4491 0,-9.1658 -0.3252,-1.2978 -0.7976,-2.3461 -1.4257,-3.0552 -0.628,-0.7091 -1.357,-1.1202 -2.5461,-1.1202 z m 1.6294,1.6294 1.7867,0 c 0.5202,0 1.1993,0.4194 1.324,0.5602 0.3625,0.4093 0.78,1.2386 1.0694,2.3932 0.8895,3.5416 0.8915,5.7515 0.05,8.2491 -0.4517,1.347 -0.9205,2.6142 -1.2729,3 -0.3184,0.3395 -1,0.5093 -1.1713,0.5093 l -4.7865,-0.051 -12.0173,0 0,4.9384 10.052,0 0,2 c 0,0.727 -0.9733,1.1789 -1.1408,1.3239 -0.4872,0.4219 -1.3508,0.8359 -2.3423,1.1202 -3.223,0.9264 -5.5,0.7859 -8.1984,0 -1.0211,-0.2975 -1.9061,-0.7339 -2.4069,-1.1595 -0.5008,-0.4256 -0.5316,-0.7741 -0.6238,-1.285 l -0.056,-9.0129 c -0.013,-2.0224 0.6457,-2.8084 2.3748,-2.8084 l 8.2491,0 c 4.9233,0 9.1103,-4.3502 9.1103,-9.0052 1e-4,-0.2574 -10e-5,-0.5149 -10e-5,-0.7723 z" opacity="0.384" fill="#fff"/>
<path d="m 13.9847,7.3199 c 0,-2.7319 0.7324,-4.2182 4.7772,-4.926 2.7462,-0.4813 6.2673,-0.5414 9.5513,0 2.5939,0.4282 4.7774,2.3604 4.7774,4.926 l 0,9.0134 c 0,2.6434 -2.1198,4.8091 -4.7774,4.8091 l -8.6621,0.4788 c -3.2414,0 -6.589,2.8321 -6.589,5.957 l -0.2736,3.777 -3.284,0 c -2.7779,0 -4.3951,-2.0029 -5.0745,-4.8056 -0.9166,-3.7651 -0.8776,-6.0088 0,-9.6147 0.7608,-3.1461 3.192,-4.8058 5.7,-4.8058 l 3.5848,0 c 0,0 8.9448,-0.035 0,-0.032 l 0,-4.7771 0,0 z" fill="url(#lg6)"/>
<path d="m 16.3733,6.7218 c 0,-1 0.8,-1.8048 1.7906,-1.8048 0.9873,0 1.7907,0.8068 1.7907,1.8048 0,0.9944 -0.8034,1.8012 -1.7907,1.8012 -0.9908,0 -1.7906,-0.8068 -1.7906,-1.8012 z" fill="#fff"/>
<path d="M 22.7173,1.9955 C 21.3039,2.0297 19.9469,2.1923 18.7455,2.4028 14.7007,3.1106 14.01,4.6102 14.01,7.3421 l -0.2952,4.787 -3.3203,-3e-4 c -2.7779,0 -5.1968,1.6406 -5.9576,4.7864 -0.5165,2.1225 -0.7504,3.7842 -0.6621,5.5504 6.2924,-7.1319 13.0442,-7.6531 16.3965,-7.638 6.6376,0.029 9.7637,-1.6029 12.9338,-5.1939 l 0,-2.2914 c 0,-2.5655 -2.1926,-4.511 -4.7865,-4.9392 C 26.4714,2.0983 24.5345,1.9515 22.7173,1.9955 z" opacity="0.377" fill="url(#lg5)"/>
<path d="m 18.696,2.6271 c 3.6201,-1.0404 6.5255,-0.8811 9.551,0 2.5268,0.7361 4.7787,2.24 4.7774,4.8057 l 0,9.7315 c 0,1.3662 -1.9746,4.5293 -4.7726,4.5293 l -8.8988,0 c -2.4983,0 -5.997,2.7217 -5.997,5.981 l 0,3.7937 -4.21,0 c -2.7815,0 -4.0909,-2.0667 -4.7774,-4.8058 -0.9555,-3.8041 -1,-6.6493 0,-9.6148 0.9661,-2.8806 2,-5.1477 4.7774,-5.1477 l 4.2985,0 10.03,0 0,0.019 -10.03,-0.034 0.019,-4.8733 c -0.026,-1.9965 2.4146,-3.5524 5.2323,-4.3845 z" fill="none" stroke="#274e70" stroke-width="1.63"/>
<path d="m 12.5337,30.6538 0,-2.796 c 0,-3.7246 3.3953,-7.0287 7.0461,-7.0287 l 8.6839,0 c 2.1549,0 4.024,-2.2411 4.0042,-4.3821 L 32.1845,7.434 C 32.1748,6.3895 31.8123,5.6105 31.0642,4.9389 30.3163,4.2673 29.1916,3.7558 28.009,3.4113 c -2.9166,-0.8494 -5.5762,-1.0023 -9.0639,0 -1.1326,0.3248 -2.6396,0.94 -3.3976,1.5964 -0.7582,0.6564 -1.3076,1.296 -1.3076,2.4263 l 0,3.6298 10.0519,0 0,1.6804 -15.1743,-0.051 c -1.2,0 -1.788,0.4724 -2.3844,1.1634 -0.5964,0.6908 -1.1149,2.0467 -1.5874,3.4559 -0.9456,2.8096 -0.9335,5.449 0,9.1657 0.3252,1.2978 0.7976,2.3461 1.4258,3.0552 0.628,0.7092 1.357,1.1203 2.546,1.1203 l 3.4162,0 z m -1.6295,-1.6295 -1.7867,0 c -0.52,0 -1.2,-0.4194 -1.3239,-0.56 C 7.431,28.0549 7.0135,27.2255 6.7241,26.0709 5.8346,22.5294 5.8327,20.3196 6.6736,17.8218 7.1253,16.475 7.5941,15.2077 7.9466,14.8319 8.265,14.4926 8.9375,14.3227 9.1178,14.3227 l 16.8038,0.051 0,-4.9394 -10.0519,0 0,-2 c 0,-0.727 0.9732,-1.1789 1.1407,-1.3239 0.4873,-0.4219 1.3509,-0.8359 2.3424,-1.12 3.2229,-0.9262 5.5,-0.7858 8.1983,0 1.0212,0.2975 1.9061,0.7339 2.3932,1.1712 0.1733,0.1352 0.2646,0.2973 0.4078,0.4582 0.1987,0.237 0.1552,0.55023 0.2011,0.8147 l 0,9.013 c 0,1.2357 -1.0565,2.7527 -2.2913,2.7527 l -8.6839,0 c -4.5897,0 -8.6756,4.0029 -8.6756,8.6581 0,0.3875 0,1.166 0,1.166 z" opacity="0.165" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,394 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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.0"
width="48"
height="48"
id="svg13684"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Stats.svg"
inkscape:export-filename="/home/glic3rinu/orchestra/django-orchestra/orchestra/static/orchestra/icons/apps/Stats.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata
id="metadata77">
<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></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="640"
inkscape:window-height="480"
id="namedview75"
showgrid="false"
inkscape:zoom="4.9166667"
inkscape:cx="24"
inkscape:cy="24"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg13684" />
<defs
id="defs3">
<linearGradient
x1="-20.75"
y1="29"
x2="-19.5"
y2="18.75"
id="G1"
xlink:href="#G2"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="G2">
<stop
id="stop6689"
style="stop-color:#fff"
offset="0" />
<stop
id="stop6691"
style="stop-color:#fff;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
x1="-20.75"
y1="29"
x2="-19.5"
y2="18.75"
id="G3"
xlink:href="#G2"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="G4">
<stop
id="stop6721"
style="stop-color:#73d216"
offset="0" />
<stop
id="stop6723"
style="stop-color:#d5f7b3"
offset="1" />
</linearGradient>
<linearGradient
x1="-17.863041"
y1="30.827509"
x2="-20.821646"
y2="25.015009"
id="G0"
xlink:href="#G4"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="G5">
<stop
id="stop6713"
style="stop-color:#5b8ccb"
offset="0" />
<stop
id="stop6715"
style="stop-color:#3465a4"
offset="1" />
</linearGradient>
<linearGradient
x1="-16.387411"
y1="24.453547"
x2="-9.7352734"
y2="28.195539"
id="G6"
xlink:href="#G5"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="G7">
<stop
id="stop6701"
style="stop-color:#ff7171"
offset="0" />
<stop
id="stop6703"
style="stop-color:#cc0000"
offset="1" />
</linearGradient>
<linearGradient
x1="-22.976406"
y1="18.516047"
x2="-14.360273"
y2="33.016045"
id="G8"
xlink:href="#G7"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="G9">
<stop
id="stop4544"
style="stop-color:#000"
offset="0" />
<stop
id="stop4546"
style="stop-color:#000;stop-opacity:0"
offset="1" />
</linearGradient>
<radialGradient
cx="24.306795"
cy="42.07798"
r="15.821514"
fx="24.306795"
fy="42.07798"
id="R1"
xlink:href="#G9"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.284916,0,30.08928)" />
<linearGradient
id="G10">
<stop
id="stop2458"
style="stop-color:#000"
offset="0" />
<stop
id="stop2460"
style="stop-color:#000;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
id="G11">
<stop
id="stop270"
style="stop-color:#a3a3a3"
offset="0" />
<stop
id="stop271"
style="stop-color:#4c4c4c"
offset="1" />
</linearGradient>
<radialGradient
cx="8.824419"
cy="3.7561285"
r="37.751713"
fx="8.824419"
fy="3.7561285"
id="R2"
xlink:href="#G11"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.971646,0,0,1.034707,3.240408,0.495684)" />
<linearGradient
id="G12">
<stop
id="stop260"
style="stop-color:#fafafa"
offset="0" />
<stop
id="stop261"
style="stop-color:#bbbbbb"
offset="1" />
</linearGradient>
<radialGradient
cx="33.966679"
cy="35.736916"
r="86.70845"
fx="33.966679"
fy="35.736916"
id="R3"
xlink:href="#G12"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.963839,0,0,1.043088,-0.124825,-0.15197)" />
<linearGradient
id="G13">
<stop
id="stop15664"
style="stop-color:#fff"
offset="0" />
<stop
id="stop15666"
style="stop-color:#f8f8f8"
offset="1" />
</linearGradient>
<radialGradient
cx="8.1435566"
cy="7.2678967"
r="38.158695"
fx="8.1435566"
fy="7.2678967"
id="R4"
xlink:href="#G13"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.974777,0,0,1.034091,3.161873,0.559274)" />
<radialGradient
cx="28.283663"
cy="47.400623"
r="13.804391"
fx="28.283663"
fy="47.400623"
id="R5"
xlink:href="#G10"
gradientUnits="userSpaceOnUse"
gradientTransform="scale(1.164226,0.85894)" />
</defs>
<g
id="layer1"
style="display:inline">
<path
d="M 40.128309,42.07798 A 15.821514,4.5078058 0 1 1 8.485281,42.07798 A 15.821514,4.5078058 0 1 1 40.128309,42.07798 z"
transform="matrix(1.169294,0,0,0.776431,-4.394955,10.82935)"
id="path3667"
style="opacity:0.56725147;fill:url(#R1);fill-rule:evenodd" />
<rect
width="34.996506"
height="40.997345"
rx="1.1490482"
ry="1.1490481"
x="6.5017405"
y="3.5013213"
id="rect15391"
style="fill:url(#R3);fill-rule:nonzero;stroke:url(#R2);stroke-width:1;stroke-linecap:round;stroke-linejoin:round" />
<rect
width="32.996056"
height="38.996326"
rx="0.14904846"
ry="0.14904855"
x="7.5033512"
y="4.5018268"
id="rect15660"
style="fill:none;fill-rule:nonzero;stroke:url(#R4);stroke-width:1;stroke-linecap:round;stroke-linejoin:round" />
<path
d="M 10,6.002203 L 10,10.966297 L 10,41.002203 L 20,41 L 20,11 L 38,11 L 38,6.002203 L 10,6.002203 z"
id="rect13655"
style="fill:#000;fill-opacity:0.21052629;fill-rule:evenodd" />
<path
d="M 37.500415,10.502203 L 10.499583,10.502203"
id="path13660"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.500755,16.5 L 10.49923,16.5"
id="path13662"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.500755,22.5 L 10.49923,22.5"
id="path13664"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.500755,28.5 L 10.49923,28.5"
id="path13666"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.501332,34.5 L 10.499823,34.5"
id="path13668"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.500755,40.5 L 10.49923,40.5"
id="path13682"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.511644,13.5 L 10.5,13.5"
id="path2464"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.500755,19.5 L 10.49923,19.5"
id="path2466"
style="fill:none;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.500755,25.5 L 10.49923,25.5"
id="path2468"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.500755,31.5 L 10.49923,31.5"
id="path2470"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.500755,37.5 L 10.49923,37.5"
id="path2472"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
<path
d="M 37.5,6.4997386 L 37.5,40.5003"
id="path2485"
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.15789466" />
<path
d="M 31.5,6.4996867 L 31.5,40.500315"
id="path2487"
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.15789466" />
<path
d="M 25.5,6.4996865 L 25.5,40.500314"
id="path2489"
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.15789466" />
<path
d="M 19.5,6.4996867 L 19.5,40.500315"
id="path2491"
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.15789466" />
<path
d="M 10.5,6.4996867 L 10.5,40.500315"
id="path2493"
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.15789466" />
<path
d="M 37.500227,6.502203 L 10.49946,6.502203"
id="path2495"
style="fill:#000;fill-opacity:0.15789466;fill-rule:evenodd;stroke:#000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" />
</g>
<g
id="layer2"
style="display:inline">
<path
d="M 49,40.714287 A 16.071428,11.857142 0 1 1 16.857141,40.714287 A 16.071428,11.857142 0 1 1 49,40.714287 z"
transform="matrix(0.92,0,0,0.92,2.777143,0.114286)"
id="path1693"
style="fill:url(#R5);fill-rule:evenodd" />
<g
transform="translate(51,9.12499)"
id="g6727">
<path
d="M -27.528542,18.092794 C -30.097576,19.791125 -31.511475,22.097833 -31.511475,24.590696 L -31.511475,26.659988 C -31.511475,29.150828 -30.097576,31.458211 -27.528542,33.156541 C -25.102053,34.760445 -21.895416,35.644009 -18.499359,35.644009 C -15.104587,35.644009 -11.89795,34.760445 -9.4701774,33.156541 C -6.9024275,31.458211 -5.4885277,29.151503 -5.4885277,26.659988 L -5.4885277,24.590696 C -5.4885277,22.097833 -6.9030696,19.79045 -9.4701774,18.092794 C -11.897308,16.490239 -15.103945,15.606001 -18.499359,15.606001 C -21.895416,15.606001 -25.102053,16.490239 -27.528542,18.092794 z"
id="path3931"
style="fill:#670000;fill-rule:nonzero" />
<path
d="M -7.0244261,24.453547 C -8.4030105,21.067003 -13.077484,18.573465 -18.636768,18.573465 C -24.196053,18.573465 -28.870526,21.067003 -30.249111,24.453547 L -30.663906,24.453547 L -30.663906,26.523514 C -30.663906,30.913678 -25.27863,34.472213 -18.636768,34.472213 C -11.994265,34.472213 -6.6102729,30.913678 -6.6102729,26.523514 L -6.6102729,24.453547 L -7.0244261,24.453547 L -7.0244261,24.453547 z"
id="path3933"
style="fill:#a40000;fill-rule:nonzero" />
<path
d="M -6.6102729,24.453547 C -6.6102729,28.844385 -11.994265,32.402921 -18.636768,32.402921 C -25.279272,32.402921 -30.663906,28.844385 -30.663906,24.453547 C -30.663906,20.062708 -25.27863,16.504173 -18.636768,16.504173 C -11.994265,16.504173 -6.6102729,20.062708 -6.6102729,24.453547 L -6.6102729,24.453547 z"
id="path3935"
style="fill:url(#G8);fill-rule:nonzero" />
<path
d="M -6.6102729,26.833098 L -6.6256833,24.666681 C -7.9297843,29.167459 -10.862246,31.074203 -14.549173,32.007678 L -14.549173,34.002103 C -10.558534,32.998483 -6.9871844,30.713358 -6.6102729,26.833098 L -6.6102729,26.833098 z"
id="path3937"
style="fill:#204a87;fill-rule:nonzero" />
<path
d="M -6.6102729,24.453547 C -6.8857329,29.533025 -13.16802,31.849176 -14.571646,31.937532 L -18.637411,24.453547 L -6.610915,24.453547 L -6.6102729,24.453547 z"
id="path3939"
style="fill:url(#G6);fill-rule:nonzero" />
<path
d="M -21.154435,34.298198 L -21.154435,32.228906 C -18.891039,32.523652 -16.814494,32.575587 -14.571646,32.015097 L -14.549173,34.002778 C -16.428593,34.619249 -19.36876,34.648251 -21.154435,34.298873 L -21.154435,34.298198 z"
id="path3941"
style="fill:#4e9a06;fill-rule:nonzero" />
<path
d="M -18.637411,24.454221 L -14.571646,31.937532 C -17.06106,32.88652 -21.154435,32.228906 -21.154435,32.228906 L -18.637411,24.454221 z"
id="path3943"
style="fill:url(#G0);fill-rule:nonzero" />
<path
d="M -6.875,24.375 A 11.75,7.75 0 1 1 -30.375,24.375 A 11.75,7.75 0 1 1 -6.875,24.375 z"
transform="matrix(0.979592,0,0,0.979592,-0.380102,0.497449)"
id="path5959"
style="opacity:0.31111115;fill:none;stroke:url(#G3);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter" />
<path
d="M -6.875,24.375 A 11.75,7.75 0 1 1 -30.375,24.375 A 11.75,7.75 0 1 1 -6.875,24.375 z"
transform="matrix(0.979592,0,0,0.979592,-0.380102,2.497449)"
id="path6707"
style="opacity:0.13333327;fill:none;stroke:url(#G1);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,177 @@
<?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/glic3rinu/orchestra/django-orchestra/orchestra/static/orchestra/icons/apps/SymbolicLink.png"
width="48px"
height="48px"
id="svg11300"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="SymbolicLink.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs3">
<linearGradient
id="linearGradient11520">
<stop
id="stop11522"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop11524"
offset="1.0000000"
style="stop-color:#dcdcdc;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient11508"
inkscape:collect="always">
<stop
id="stop11510"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop11512"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient11508"
id="radialGradient1348"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.000000,0.000000,0.000000,0.338462,-1.435476e-15,29.48178)"
cx="30.203562"
cy="44.565483"
fx="30.203562"
fy="44.565483"
r="6.5659914" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient11520"
id="radialGradient1366"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.995058,-1.651527e-32,0.000000,1.995058,-24.32488,-35.70087)"
cx="24.445690"
cy="35.878170"
fx="24.445690"
fy="35.878170"
r="20.530962" />
</defs>
<sodipodi:namedview
stroke="#ef2929"
fill="#888a85"
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="0.25490196"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="28.252398"
inkscape:cy="22.342711"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:showpageshadow="false"
inkscape:window-width="872"
inkscape:window-height="707"
inkscape:window-x="271"
inkscape:window-y="164"
inkscape:window-maximized="0" />
<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>Symbolic Link</dc:title>
<dc:subject>
<rdf:Bag>
<rdf:li>emblem</rdf:li>
<rdf:li>symbolic</rdf:li>
<rdf:li>link</rdf:li>
<rdf:li>pointer</rdf:li>
<rdf:li>io</rdf:li>
<rdf:li>file</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">
<path
sodipodi:type="arc"
style="opacity:0.40641710;color:#000000;fill:url(#radialGradient1348);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:2.8141584;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
id="path11530"
sodipodi:cx="30.203562"
sodipodi:cy="44.565483"
sodipodi:rx="6.5659914"
sodipodi:ry="2.2223356"
d="M 36.769553 44.565483 A 6.5659914 2.2223356 0 1 1 23.637570,44.565483 A 6.5659914 2.2223356 0 1 1 36.769553 44.565483 z"
transform="matrix(2.460049,0.000000,0.000000,2.460049,-49.40946,-67.96374)" />
<rect
ry="5.4548240"
rx="5.4548240"
y="3.5233452"
x="4.4147282"
height="40.061924"
width="40.061924"
id="rect11518"
style="opacity:1.0000000;color:#000000;fill:url(#radialGradient1366);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#9b9b9b;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
<rect
style="opacity:1.0000000;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
id="rect11528"
width="37.696587"
height="37.696587"
x="5.5973887"
y="4.7060070"
rx="4.2426391"
ry="4.2426391" />
<path
sodipodi:nodetypes="ccccccc"
id="path2177"
d="M 11.500037,31.436501 C 11.940474,20.09759 22.043105,11.32322 32.158766,21.979434 L 37.068811,17.246167 C 37.068811,17.246167 37.088388,32 37.088388,32 L 22.160133,31.978069 C 22.160133,31.978069 26.997745,27.140456 26.997745,27.140456 C 18.528582,18.264221 13.291696,25.230495 11.500037,31.436501 z "
style="opacity:0.69886361;color:#000000;fill:#888a85;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.9999997;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,127 @@
<?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"
id="svg3201"
version="1.1"
inkscape:version="0.48.3.1 r9886"
width="48"
height="48"
sodipodi:docname="WordPressMu.svg"
inkscape:export-filename="/home/glic3rinu/orchestra/django-orchestra/orchestra/static/orchestra/icons/apps/WordPressMu.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata
id="metadata3207">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3205">
<radialGradient
r="10.625"
fy="4.625"
fx="62.625"
cy="4.625"
cx="62.625"
gradientTransform="matrix(2.2657407,0,0,0.74122745,-117.89261,32.892968)"
gradientUnits="userSpaceOnUse"
id="radialGradient3610"
xlink:href="#linearGradient8838-7"
inkscape:collect="always" />
<linearGradient
id="linearGradient8838-7">
<stop
id="stop8840-0"
style="stop-color:black;stop-opacity:1"
offset="0" />
<stop
id="stop8842-7"
style="stop-color:black;stop-opacity:0"
offset="1" />
</linearGradient>
<radialGradient
r="10.625"
fy="4.625"
fx="62.625"
cy="4.625"
cx="62.625"
gradientTransform="matrix(2.2657407,0,0,0.74122745,-117.84341,35.950626)"
gradientUnits="userSpaceOnUse"
id="radialGradient3708"
xlink:href="#linearGradient8838-7"
inkscape:collect="always" />
</defs>
<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="namedview3203"
showgrid="false"
inkscape:zoom="5.5096774"
inkscape:cx="61.540584"
inkscape:cy="23.568076"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg3201" />
<path
inkscape:connector-curvature="0"
d="m 48.122094,39.37881 c 0,4.34954 -10.77808,7.87555 -24.0735,7.87555 -13.29542,0 -24.07349952,-3.52601 -24.07349952,-7.87555 0,-4.34955 10.77807952,-7.87556 24.07349952,-7.87556 13.29542,0 24.0735,3.52601 24.0735,7.87556 l 0,0 z"
id="path8836-9"
style="opacity:0.3;fill:url(#radialGradient3708);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999988;marker:none;visibility:visible;display:inline;overflow:visible" />
<rect
style="fill:#eeeeec;stroke:#eeeeec"
id="rect3747"
width="31.308554"
height="23.776344"
x="8.3035679"
y="14.241219"
ry="11.888172" />
<path
style="fill:#464342;fill-opacity:1"
d="M 19.03125 4.90625 C 15.791437 4.896058 12.606484 6.0795174 10.15625 8.375 C 7.6092021 10.76118 6.312211 14.450111 6.28125 17.8125 L 6.25 19.03125 L 5.46875 19.4375 C 3.8068539 20.293995 2.1311692 21.968811 1.1875 23.65625 C -1.095219 27.738139 -0.39657021 33.729525 2.90625 37.0625 C 4.8794402 39.053705 7.2061377 40.127815 10.28125 40.4375 C 10.493713 40.4589 17.204872 40.47795 25.1875 40.46875 L 39.6875 40.4375 L 40.625 40.1875 C 44.409275 39.18276 47.118432 36.371676 47.75 32.75 C 47.84317 32.215716 47.90625 30.63137 47.90625 30.34375 C 47.90625 29.552142 47.626845 27.993609 47.3125 27.15625 C 46.375552 24.660404 44.118781 22.499477 41.5625 21.65625 C 41.026677 21.479501 40.55624 21.3282 40.53125 21.3125 C 40.50626 21.29679 40.62504 21.03865 40.78125 20.75 C 42.216372 18.098165 41.324889 13.94101 38.78125 12.25 C 36.569496 10.779627 33.642565 10.725217 31.5625 12.125 C 31.467146 12.189168 31.45817 12.1973 31.375 12.25 C 35.289322 15.015997 37.843598 19.572186 37.84375 24.71875 C 37.84375 33.135623 31.009377 39.96875 22.59375 39.96875 C 14.177874 39.96875 7.3125 33.135623 7.3125 24.71875 C 7.3125 16.302874 14.177874 9.4375 22.59375 9.4375 C 25.479095 9.4375 28.164756 10.25928 30.46875 11.65625 C 29.357794 9.4708026 27.196338 7.4129981 24.78125 6.25 C 22.930278 5.3586557 20.975138 4.9123651 19.03125 4.90625 z M 22.59375 10.15625 C 14.563551 10.15625 8.03125 16.6888 8.03125 24.71875 C 8.03125 32.749198 14.5638 39.28125 22.59375 39.28125 C 30.623451 39.28125 37.15625 32.749198 37.15625 24.71875 C 37.15625 16.6888 30.623451 10.15625 22.59375 10.15625 z M 21.75 11.625 C 22.031322 11.606943 22.307856 11.625 22.59375 11.625 C 26.002555 11.625 29.107992 12.928322 31.4375 15.0625 C 31.380944 15.059261 31.308051 15.03125 31.25 15.03125 C 29.964162 15.03125 29.0625 16.171379 29.0625 17.375 C 29.0625 18.45355 29.680027 19.35895 30.34375 20.4375 C 30.84229 21.309757 31.4375 22.413052 31.4375 24.03125 C 31.4375 25.152154 31.003558 26.470213 30.4375 28.28125 L 29.125 32.65625 L 24.40625 18.5625 C 25.194047 18.521142 25.875 18.4375 25.875 18.4375 C 26.58033 18.354036 26.518827 17.333393 25.8125 17.375 C 25.8125 17.375 23.681802 17.53125 22.3125 17.53125 C 21.025914 17.53125 18.875 17.375 18.875 17.375 C 18.169421 17.333393 18.075671 18.396142 18.78125 18.4375 C 18.78125 18.4375 19.451169 18.521142 20.15625 18.5625 L 22.1875 24.15625 L 19.34375 32.75 L 14.5625 18.5625 C 15.351792 18.521142 16.0625 18.4375 16.0625 18.4375 C 16.767581 18.354036 16.674578 17.333393 15.96875 17.375 C 15.96875 17.375 13.869551 17.53125 12.5 17.53125 C 12.254094 17.53125 11.963446 17.509218 11.65625 17.5 C 13.851141 14.167371 17.530176 11.895861 21.75 11.625 z M 34.0625 18.4375 C 35.085241 20.302601 35.687749 22.44231 35.6875 24.71875 C 35.6875 29.549177 33.048895 33.761288 29.15625 36.03125 L 33.15625 24.46875 C 33.903686 22.601158 34.15625 21.109941 34.15625 19.78125 C 34.15625 19.299652 34.118807 18.854569 34.0625 18.4375 z M 10.625 19.375 L 16.875 36.5 C 12.507484 34.377532 9.5 29.901469 9.5 24.71875 C 9.5 22.820513 9.8984926 21.003413 10.625 19.375 z M 22.8125 25.84375 L 26.84375 36.875 C 26.86991 36.939778 26.902371 37.006442 26.9375 37.0625 C 25.57642 37.541108 24.118519 37.8125 22.59375 37.8125 C 21.30841 37.8125 20.047976 37.626067 18.875 37.28125 L 22.8125 25.84375 z "
id="path3726" />
<g
id="g22"
transform="matrix(0.21649934,0,0,0.21649934,10.650797,12.186804)" />
<g
id="g3002"
transform="matrix(0.68558415,0,0,0.68558415,6.1370097,8.023588)"
style="fill:#5c3566">
<g
transform="translate(0,-74.523003)"
id="Layer_1"
style="fill:#5c3566" />
<g
transform="matrix(0.36340573,0,0,0.36340573,1.731598,2.0710297)"
id="g6"
style="fill:#5c3566">
<g
id="g22-5"
style="fill:#5c3566" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -16,7 +16,7 @@
width="48"
height="48"
sodipodi:docname="saas.svg"
inkscape:export-filename="/home/glic3/orchestra/django-orchestra/orchestra/static/orchestra/icons/saas.png"
inkscape:export-filename="/home/glic3rinu/orchestra/django-orchestra/orchestra/static/orchestra/icons/saas.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<metadata

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -14,7 +14,7 @@
<div style="margin:20px;">
{% if plugin.icon %}
<div id="module_2" class="dashboard-module" style="display: inline-block;">
<h2>Software as a Service</h2>
<h2>{{ plugin_title }}</h2>
<div class="dashboard-module-content">
<ul class="fluent-dashboard-appiconlist clearfix" style="padding: 0">
{% for plugin in plugins %}

View File

@ -174,7 +174,6 @@ UNITS_CONVERSIONS = {
}
def unit_to_bytes(unit):
unit = unit.upper()
for bytes, units in UNITS_CONVERSIONS.iteritems():
if unit in units:
return bytes

View File

@ -1,4 +1,6 @@
import collections
import random
import string
def import_class(cls):
@ -8,6 +10,10 @@ def import_class(cls):
return getattr(module, cls)
def random_ascii(length):
return ''.join([random.choice(string.hexdigits) for i in range(0, length)]).lower()
class OrderedSet(collections.MutableSet):
def __init__(self, iterable=None):
self.end = end = []

View File

@ -1,7 +1,5 @@
import datetime
import os
import string
import random
from functools import wraps
from django.conf import settings
@ -15,9 +13,8 @@ from xvfbwrapper import Xvfb
from orchestra.apps.accounts.models import Account
from .python import random_ascii
def random_ascii(length):
return ''.join([random.choice(string.hexdigits) for i in range(0, length)]).lower()
class AppDependencyMixin(object):