diff --git a/orchestra/admin/menu.py b/orchestra/admin/menu.py index 3fb6bffc..c3e7b4f1 100644 --- a/orchestra/admin/menu.py +++ b/orchestra/admin/menu.py @@ -38,49 +38,71 @@ def get_services(): return sorted(result, key=lambda i: i.title) -def get_accounts(): - accounts = [ +def get_account_items(): + childrens = [ items.MenuItem(_("Accounts"), reverse('admin:accounts_account_changelist')) ] if isinstalled('orchestra.apps.contacts'): url = reverse('admin:contacts_contact_changelist') - accounts.append(items.MenuItem(_("Contacts"), url)) + childrens.append(items.MenuItem(_("Contacts"), url)) if isinstalled('orchestra.apps.users'): url = reverse('admin:users_user_changelist') users = [items.MenuItem(_("Users"), url)] if isinstalled('rest_framework.authtoken'): tokens = reverse('admin:authtoken_token_changelist') users.append(items.MenuItem(_("Tokens"), tokens)) - accounts.append(items.MenuItem(_("Users"), url, children=users)) + childrens.append(items.MenuItem(_("Users"), url, children=users)) if isinstalled('orchestra.apps.prices'): url = reverse('admin:prices_pack_changelist') - accounts.append(items.MenuItem(_("Packs"), url)) + childrens.append(items.MenuItem(_("Packs"), url)) if isinstalled('orchestra.apps.orders'): url = reverse('admin:orders_order_changelist') - accounts.append(items.MenuItem(_("Orders"), url)) - return accounts - - -def get_administration(): - administration = [] - return administration - - -def get_administration_models(): - administration_models = [] - if isinstalled('orchestra.apps.orchestration'): - administration_models.append('orchestra.apps.orchestration.*') - if isinstalled('djcelery'): - administration_models.append('djcelery.*') + childrens.append(items.MenuItem(_("Orders"), url)) if isinstalled('orchestra.apps.issues'): - administration_models.append('orchestra.apps.issues.*') - if isinstalled('orchestra.apps.resources'): - administration_models.append('orchestra.apps.resources.*') - if isinstalled('orchestra.apps.miscellaneous'): - administration_models.append('orchestra.apps.miscellaneous.models.MiscService') + url = reverse('admin:issues_ticket_changelist') + childrens.append(items.MenuItem(_("Tickets"), url)) + return childrens + + +def get_administration_items(): + childrens = [] if isinstalled('orchestra.apps.orders'): - administration_models.append('orchestra.apps.orders.models.Service') - return administration_models + url = reverse('admin:orders_service_changelist') + childrens.append(items.MenuItem(_("Services"), url)) + if isinstalled('orchestra.apps.orchestration'): + route = reverse('admin:orchestration_route_changelist') + backendlog = reverse('admin:orchestration_backendlog_changelist') + server = reverse('admin:orchestration_server_changelist') + childrens.append(items.MenuItem(_("Orchestration"), route, children=[ + items.MenuItem(_("Routes"), route), + items.MenuItem(_("Backend logs"), backendlog), + items.MenuItem(_("Servers"), server), + ])) + if isinstalled('orchestra.apps.resources'): + resource = reverse('admin:resources_resource_changelist') + data = reverse('admin:resources_resourcedata_changelist') + monitor = reverse('admin:resources_monitordata_changelist') + childrens.append(items.MenuItem(_("Resources"), resource, children=[ + items.MenuItem(_("Resources"), resource), + items.MenuItem(_("Data"), data), + items.MenuItem(_("Monitoring"), monitor), + ])) + if isinstalled('orchestra.apps.miscellaneous'): + url = reverse('admin:miscellaneous_miscservice_changelist') + childrens.append(items.MenuItem(_("Miscellaneous"), url)) + if isinstalled('orchestra.apps.issues'): + url = reverse('admin:issues_queue_changelist') + childrens.append(items.MenuItem(_("Issue queues"), url)) + if isinstalled('djcelery'): + task = reverse('admin:djcelery_taskstate_changelist') + periodic = reverse('admin:djcelery_periodictask_changelist') + worker = reverse('admin:djcelery_workerstate_changelist') + childrens.append(items.MenuItem(_("Celery"), task, children=[ + items.MenuItem(_("Tasks"), task), + items.MenuItem(_("Periodic tasks"), periodic), + items.MenuItem(_("Workers"), worker), + ])) + return childrens class OrchestraMenu(Menu): @@ -99,12 +121,11 @@ class OrchestraMenu(Menu): items.MenuItem( _("Accounts"), reverse('admin:accounts_account_changelist'), - children=get_accounts() + children=get_account_items() ), - items.AppList( + items.MenuItem( _("Administration"), - models=get_administration_models(), - children=get_administration() + children=get_administration_items() ), items.MenuItem("API", api_link(context)) ] diff --git a/orchestra/admin/utils.py b/orchestra/admin/utils.py index 9340e8ed..70a0c77d 100644 --- a/orchestra/admin/utils.py +++ b/orchestra/admin/utils.py @@ -76,7 +76,8 @@ def admin_link(*args, **kwargs): order = kwargs.pop('order', field) popup = kwargs.pop('popup', False) - def display_link(self, instance): + def display_link(*args): + instance = args[-1] obj = getattr(instance, field, instance) if not getattr(obj, 'pk', None): return '---' @@ -95,7 +96,7 @@ def admin_link(*args, **kwargs): def colored(field_name, colours, description='', verbose=False, bold=True): """ returns a method that will render obj with colored html """ - def colored_field(modeladmin, obj, field=field_name, colors=colours, verbose=verbose): + def colored_field(obj, field=field_name, colors=colours, verbose=verbose): value = escape(get_field_value(obj, field)) color = colors.get(value, "black") if verbose: @@ -133,11 +134,12 @@ def admin_date(field, **kwargs): default = kwargs.pop('default', '') order = kwargs.pop('order', field) - def display_date(self, instance): + def display_date(*args): + instance = args[-1] value = get_field_value(instance, field) if not value: return default - return '
{1}
'.format( + return '{1}'.format( escape(str(value)), escape(naturaldate(value)), ) display_date.short_description = _(field.replace('_', ' ')) diff --git a/orchestra/apps/accounts/admin.py b/orchestra/apps/accounts/admin.py index 2f8f7024..fd046721 100644 --- a/orchestra/apps/accounts/admin.py +++ b/orchestra/apps/accounts/admin.py @@ -60,8 +60,9 @@ class AccountAdmin(ExtendedModelAdmin): if not account.is_active: messages.warning(request, 'This account is disabled.') context = { + # TODO not services but everythin (payments, bills, etc) 'services': sorted( - [ model._meta for model in services.get() ], + [ model._meta for model in services.get() if model is not Account ], key=lambda i: i.verbose_name_plural.lower() ) } diff --git a/orchestra/apps/issues/admin.py b/orchestra/apps/issues/admin.py index 4f37dc7c..d0c43ea8 100644 --- a/orchestra/apps/issues/admin.py +++ b/orchestra/apps/issues/admin.py @@ -55,8 +55,8 @@ class MessageReadOnlyInline(admin.TabularInline): def content_html(self, msg): context = { 'number': msg.number, - 'time': display_timesince(msg.created_on), - 'author': link('author')(self, msg) if msg.author else msg.author_name, + 'time': admin_date('created_on')(msg), + 'author': admin_link('author')(msg) if msg.author else msg.author_name, } summary = _("#%(number)i Updated by %(author)s about %(time)s") % context header = '%s
' % summary @@ -113,7 +113,7 @@ class TicketInline(admin.TabularInline): last_modified = admin_link('last_modified_on') def ticket_id(self, instance): - return '%s' % link()(self, instance) + return '%s' % admin_link()(instance) ticket_id.short_description = '#' ticket_id.allow_tags = True @@ -197,17 +197,18 @@ class TicketAdmin(ChangeListDefaultFilter, ExtendedModelAdmin): #TODO ChangeView display_creator = admin_link('creator') display_queue = admin_link('queue') display_owner = admin_link('owner') + last_modified = admin_date('last_modified_on') def display_summary(self, ticket): context = { - 'creator': link('creator')(self, ticket) if ticket.creator else ticket.creator_name, - 'created': display_timesince(ticket.created_on), + 'creator': admin_link('creator')(self, ticket) if ticket.creator else ticket.creator_name, + 'created': admin_date('created_on')(ticket), 'updated': '', } msg = ticket.messages.last() if msg: context.update({ - 'updated': display_timesince(msg.created_on), + 'updated': admin_date('created_on')(msg), 'updater': admin_link('author')(self, msg) if msg.author else msg.author_name, }) context['updated'] = '. Updated by %(updater)s about %(updated)s' % context @@ -245,10 +246,6 @@ class TicketAdmin(ChangeListDefaultFilter, ExtendedModelAdmin): #TODO ChangeView bold_subject.short_description = _("Subject") bold_subject.admin_order_field = 'subject' - def last_modified(self, instance): - return display_timesince(instance.last_modified_on) - last_modified.admin_order_field = 'last_modified_on' - def formfield_for_dbfield(self, db_field, **kwargs): """ Make value input widget bigger """ if db_field.name == 'subject': diff --git a/orchestra/apps/issues/models.py b/orchestra/apps/issues/models.py index 7922b2de..e0a8b142 100644 --- a/orchestra/apps/issues/models.py +++ b/orchestra/apps/issues/models.py @@ -85,7 +85,7 @@ class Ticket(models.Model): if self.owner: emails.append(self.owner.email) for contact in self.creator.account.contacts.all(): - if self.queue and set(contact.email_usage).union(set(self.queue.nofify)): + if self.queue and set(contact.email_usage).union(set(self.queue.notify)): emails.append(contact.email) for message in self.messages.distinct('author'): emails.append(message.author.email) diff --git a/orchestra/apps/resources/models.py b/orchestra/apps/resources/models.py index 51a0c664..dde199c3 100644 --- a/orchestra/apps/resources/models.py +++ b/orchestra/apps/resources/models.py @@ -173,7 +173,6 @@ def create_resource_relation(): resource = Resource.objects.get(content_type__model=model, name=attr, is_active=True) data = ResourceData(content_object=self.obj, resource=resource) - print data.resource_id, data.content_type_id, data.object_id setattr(self, attr, data) return data diff --git a/orchestra/conf/base_settings.py b/orchestra/conf/base_settings.py index 2672a067..213deac4 100644 --- a/orchestra/conf/base_settings.py +++ b/orchestra/conf/base_settings.py @@ -145,6 +145,7 @@ FLUENT_DASHBOARD_APP_GROUPS = ( 'orchestra.apps.prices.models.Pack', 'orchestra.apps.bills.models.Bill', 'orchestra.apps.payments.models.Transaction', + 'orchestra.apps.issues.models.Ticket', ), 'collapsible': True, }), @@ -154,7 +155,6 @@ FLUENT_DASHBOARD_APP_GROUPS = ( 'orchestra.apps.orchestration.models.Route', 'orchestra.apps.orchestration.models.BackendLog', 'orchestra.apps.orchestration.models.Server', - 'orchestra.apps.issues.models.Ticket', 'orchestra.apps.resources.models.Resource', 'orchestra.apps.resources.models.Monitor', 'orchestra.apps.orders.models.Service', @@ -185,13 +185,13 @@ FLUENT_DASHBOARD_APP_ICONS = { 'prices/pack': 'Pack.png', 'bills/bill': 'invoice.png', 'payments/transaction': 'transaction.png', + 'issues/ticket': 'Ticket_star.png', # Administration 'users/user': 'Mr-potato.png', 'djcelery/taskstate': 'taskstate.png', 'orchestration/server': 'vps.png', 'orchestration/route': 'hal.png', 'orchestration/backendlog': 'scriptlog.png', - 'issues/ticket': 'Ticket_star.png', 'resources/resource': "gauge.png", 'resources/monitor': "Utilities-system-monitor.png", } diff --git a/orchestra/static/orchestra/icons/Pack.png b/orchestra/static/orchestra/icons/Pack.png new file mode 100644 index 00000000..24d48ced Binary files /dev/null and b/orchestra/static/orchestra/icons/Pack.png differ diff --git a/orchestra/static/orchestra/icons/Pack.svg b/orchestra/static/orchestra/icons/Pack.svg new file mode 100644 index 00000000..7afdb383 --- /dev/null +++ b/orchestra/static/orchestra/icons/Pack.svg @@ -0,0 +1,4350 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/orchestra/static/orchestra/icons/Taskstate.svg b/orchestra/static/orchestra/icons/Taskstate.svg new file mode 100644 index 00000000..0471b135 --- /dev/null +++ b/orchestra/static/orchestra/icons/Taskstate.svg @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/orchestra/static/orchestra/icons/applications-other.png b/orchestra/static/orchestra/icons/applications-other.png new file mode 100644 index 00000000..8e909384 Binary files /dev/null and b/orchestra/static/orchestra/icons/applications-other.png differ diff --git a/orchestra/static/orchestra/icons/applications-other.svg b/orchestra/static/orchestra/icons/applications-other.svg new file mode 100644 index 00000000..3a141484 --- /dev/null +++ b/orchestra/static/orchestra/icons/applications-other.svg @@ -0,0 +1,807 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/orchestra/static/orchestra/icons/invoice.png b/orchestra/static/orchestra/icons/invoice.png new file mode 100644 index 00000000..6a5daa2c Binary files /dev/null and b/orchestra/static/orchestra/icons/invoice.png differ diff --git a/orchestra/static/orchestra/icons/invoice.svg b/orchestra/static/orchestra/icons/invoice.svg new file mode 100644 index 00000000..6bc4a4e9 --- /dev/null +++ b/orchestra/static/orchestra/icons/invoice.svg @@ -0,0 +1,679 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + Invoice + + + + + diff --git a/orchestra/static/orchestra/icons/taskstate.png b/orchestra/static/orchestra/icons/taskstate.png index 777c5898..9280cb7f 100755 Binary files a/orchestra/static/orchestra/icons/taskstate.png and b/orchestra/static/orchestra/icons/taskstate.png differ