123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- from django.conf import settings
- from django.conf.urls import patterns, include, url
- from django.core.urlresolvers import resolve
- from django.utils.importlib import import_module
- """
- Clean admin path if it was defined, or leave variable empty if ACP is turned off.
- """
- ADMIN_PATH = ''
- if settings.ADMIN_PATH:
- ADMIN_PATH = settings.ADMIN_PATH
- while ADMIN_PATH[:1] == '/':
- ADMIN_PATH = ADMIN_PATH[1:]
- while ADMIN_PATH[-1:] == '/':
- ADMIN_PATH = ADMIN_PATH[:-1]
- ADMIN_PATH += '/'
- """
- Admin lists sorter for admin sections and actions
- """
- class SortList(object):
- def __init__(self, unsorted):
- self.unsorted = unsorted
- def sort(self):
- # Sort and return sorted list
- order = []
- cache = {}
- for item in self.unsorted:
- if item.after:
- try:
- cache[item.after].append(item.id)
- except KeyError:
- cache[item.after] = []
- cache[item.after].append(item.id)
- else:
- order.append(item.id)
- while cache:
- for item in cache.keys():
- try:
- target_index = order.index(item)
- for new_item in cache[item]:
- target_index += 1
- order.insert(target_index, new_item)
- del cache[item]
- except ValueError:
- pass
- sorted = []
- for item in order:
- for object in self.unsorted:
- if item == object.id:
- sorted.append(object)
- break
- return sorted
- """
- Admin site section
- """
- class AdminSiteItem(object):
- def __init__(self, id, name, icon, target=None, link=None, help=None, after=None):
- self.id = id
- self.name = name
- self.help = help
- self.after = after
- self.icon = icon
- self.target = target
- self.link = link
- self.sorted = False
- """
- Admin site action
- """
- class AdminAction(AdminSiteItem):
- def __init__(self, section=None, actions=[], model=None, messages={}, urlpatterns=None, **kwargs):
- self.actions = actions
- self.section = section
- self.model = model
- self.messages = messages
- self.urlpatterns = urlpatterns
- super(AdminAction, self).__init__(**kwargs)
- def get_action_attr(self, id, attr):
- for action in self.actions:
- if action['id'] == id:
- return action[attr]
- return None
- def is_active(self, full_path, section=None):
- if section:
- action_path = '/%s%s/%s/' % (ADMIN_PATH, section, self.id)
- else:
- action_path = '/%s%s/' % (ADMIN_PATH, self.id)
- # Paths overlap = active action
- return len(action_path) <= full_path and full_path[:len(action_path)] == action_path
- """
- Admin site section
- """
- class AdminSection(AdminSiteItem):
- def __init__(self, section=None, **kwargs):
- self.actions = []
- self.last = None
- super(AdminSection, self).__init__(**kwargs)
- def get_links(self):
- links = []
- first_action = True
- for action in self.actions:
- if first_action:
- links += patterns('', url('^', include(action.urlpatterns)))
- first_action = False
- else:
- links += patterns('', url(('^%s/' % action.id), include(action.urlpatterns)))
- return links
- def is_active(self, full_path):
- action_path = '/%s%s/' % (ADMIN_PATH, self.id)
- # Paths overlap = active action
- return len(action_path) <= full_path and full_path[:len(action_path)] == action_path
- """
- Admin site class that knows ACP structure
- """
- class AdminSite(object):
- actions_index = {}
- links = []
- sections = []
- sections_index = {}
- def discover(self):
- """
- Build admin site structure
- """
- if self.links:
- return self.links
- # Found actions
- actions = []
- # Orphan actions that have no section yet
- late_actions = []
- # Load default admin site
- from misago.apps.admin.sections import ADMIN_SECTIONS
- for section in ADMIN_SECTIONS:
- self.sections.append(section)
- self.sections_index[section.id] = section
- # Loop section actions
- section_actions = import_module('misago.apps.admin.sections.%s' % section.id)
- for action in section_actions.ADMIN_ACTIONS:
- self.actions_index[action.id] = action
- if not action.after:
- action.after = self.sections_index[section.id].last
- actions.append(action)
- self.sections_index[section.id].last = action.after
- # Iterate over installed applications
- for app_name in settings.INSTALLED_APPS:
- try:
- app = import_module(app_name + '.admin')
- # Attempt to import sections
- try:
- for section in app.ADMIN_SECTIONS:
- self.sections.append(section)
- self.sections_index[section.id] = section
- except AttributeError:
- pass
- # Attempt to import actions
- try:
- for action in app.ADMIN_ACTIONS:
- self.actions_index[action.id] = action
- if action.section in self.sections_index:
- if not action.after:
- action.after = self.sections_index[action.section].last
- actions.append(action)
- self.sections_index[action.section].last = action.after
- else:
- late_actions.append(action)
- except AttributeError:
- pass
- except ImportError:
- pass
- # So actions and late actions
- actions += late_actions
- # Sorth sections and actions
- sort_sections = SortList(self.sections)
- sort_actions = SortList(actions)
- self.sections = sort_sections.sort()
- actions = sort_actions.sort()
- # Put actions in sections
- for action in actions:
- self.sections_index[action.section].actions.append(action)
- # Return ready admin routing
- first_section = True
- for section in self.sections:
- if first_section:
- self.links += patterns('', url('^', include(section.get_links())))
- first_section = False
- else:
- self.links += patterns('', url(('^%s/' % section.id), include(section.get_links())))
-
- return self.links
- def get_action(self, action):
- """
- Get admin action
- """
- return self.actions_index.get(action)
- def get_admin_index(self):
- """
- Return admin index link - first action of first section
- """
- return self.sections[0].actions[0].link
- def get_admin_navigation(self, request):
- """
- Find and return current admin navigation
- """
- sections = []
- actions = []
- active_section = False
- active_action = False
- # Loop sections, build list of sections and find active section
- for section in self.sections:
- is_active = section.is_active(request.path)
- sections.append({
- 'is_active': is_active,
- 'name': section.name,
- 'icon': section.icon,
- 'link': section.actions[0].link
- })
- if is_active:
- active_section = section
- # If no section was found to be active, default to first one
- if not active_section:
- active_section = self.sections[0]
- sections[0]['is_active'] = True
- # Loop active section actions
- for action in active_section.actions:
- is_active = action.is_active(request.path, active_section.id if active_section != self.sections[0] else None)
- actions.append({
- 'is_active': is_active,
- 'name': action.name,
- 'icon': action.icon,
- 'help': action.help,
- 'link': action.link
- })
- if is_active:
- active_action = action
- # If no action was found to be active, default to first one
- if not active_action:
- active_action = active_section.actions[0]
- actions[0]['is_active'] = True
- # Return admin navigation for this location
- return {
- 'sections': sections,
- 'actions': actions,
- 'admin_index': self.get_admin_index(),
- }
- site = AdminSite();
|