|
@@ -1,280 +1,280 @@
|
|
|
-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();
|
|
|
+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();
|