def render_admin_panel(self, req, cat, page, path_info): """ Returns the admin view and handles the form actions """ req.perm.require('TRAC_ADMIN') project = Project.get(self.env) if req.method == 'POST': myprojects_url = conf.url_home_path + "/myprojects" conf.log.exception("Redirect URL: %s" % myprojects_url) thisurl = Href(req.base_path)(req.path_info) context = Context.from_request(req) # Handle project remove if 'remove' in req.args: # Don't allow removing home if project.env_name == conf.sys_home_project_name: add_warning(req, 'Cannot remove home project') return req.redirect(thisurl) # Archive the project before removal archive = ProjectArchive() archived = archive.archive(project) if not archived: add_warning(req, 'Could not archive project "%s". Will not remove the project' % project.project_name) return req.redirect(thisurl) # Notify listeners. The project object still exists, but database does not for listener in self.project_change_listeners: listener.project_archived(project) # Do the actual project removal projects = Projects() if projects.remove_project(project): # Notify listeners. The project object still exists, but database does not for listener in self.project_change_listeners: listener.project_deleted(project) # NOTE: We no longer have project tables/session etc available req.redirect(myprojects_url) else: add_warning(req, 'Could not remove project "%s". Try again later' % project.project_name) return req.redirect(thisurl) add_script(req, 'multiproject/js/jquery-ui.js') add_script(req, 'multiproject/js/multiproject.js') add_script(req, 'multiproject/js/admin_system.js') add_stylesheet(req, 'multiproject/css/jquery-ui.css') # NOTE: Trac automatically puts 'project' dict in chrome thus it cannot be used data = {'multiproject': { 'project':project, 'home_url':conf.url_home_path }} return 'admin_system.html', data
def remove_project(self, req): """ Handler for removing project :param Request req: Trac request Handler expects to have following arguments in it: - project: Name of the project env - goto: Optional URL where to go after project removal. Defaults to /home/myprojects """ backurl = req.args.get('goto', ProjectListModule.home('myprojects')) short_name = req.args.get('project') if not short_name: return self.remove_failure(req) if req.args.get('cancel'): add_notice(req, 'Project deletion cancelled') return self.remove_failure(req) author = req.authname project = Project.get(env_name=short_name) if project is None: add_warning(req, 'Specified project does not exist!') return self.remove_failure(req) # Don't allow removing home if project.env_name == conf.sys_home_project_name: add_warning(req, 'Cannot remove home project') return self.remove_failure(req) if req.method != 'POST': return self.remove_failure(req, project=project) try: project.validate() except ProjectValidationException: req.redirect(backurl) # Check the permissions and method prjs = Projects() if ('TRAC_ADMIN' in req.perm or prjs.is_project_owner(project.env_name, author)) and req.method == 'POST': archive = ProjectArchive() # Archive the project before removal if not archive.archive(project): add_warning(req, 'Could not archive project "%s". Will not remove the project' % project.project_name) elif prjs.remove_project(project): # Notify listeners for listener in self.project_change_listeners: listener.project_deleted(project) # Notify end user add_notice(req, 'Project "%s" removed' % project.project_name) else: add_warning(req, 'Could not remove project "%s". Try again later' % project.project_name) else: add_warning(req, 'You are not allowed to remove project "%s" (check permissions and method)' % project.project_name) req.redirect(backurl)
def render_admin_panel(self, req, cat, page, path_info): req.perm.require("TRAC_ADMIN") arch = ProjectArchive() projects = arch.list() if req.method == 'POST': archived_project_id = int(req.args.get('archived_project_id', 0)) action = req.args.get('action', 'noop') try: if action == 'restore': if arch.restore(archived_project_id, self.env): add_notice(req, _('Restored project successfully')) elif action == 'remove': if arch.remove(archived_project_id): add_notice(req, _('Removed project successfully')) elif action == 'remove_expired': if arch.remove_expired(): add_notice(req, _('Removed expired projects successfully')) else: add_warning(req, _('Unknown action')) except Exception: add_warning(req, _('Failed to complete the action')) self.log.exception('Failed to {0} for project {1}'.format(action, archived_project_id)) # After post method, redirect back to listing return req.redirect(req.href('/admin/projects/prjarchive')) add_script(req, 'multiproject/js/jquery-ui.js') add_stylesheet(req, 'multiproject/css/jquery-ui.css') add_script(req, 'multiproject/js/multiproject.js') add_script(req, 'multiproject/js/admin_project_archive.js') return 'multiproject_admin_project_archive.html', {'projects': projects}
def render_admin_panel(self, req, cat, page, path_info): req.perm.require("TRAC_ADMIN") arch = ProjectArchive() projects = arch.list() if req.method == 'POST': archived_project_id = int(req.args.get('archived_project_id', 0)) action = req.args.get('action', 'noop') try: if action == 'restore': if arch.restore(archived_project_id, self.env): add_notice(req, _('Restored project successfully')) elif action == 'remove': if arch.remove(archived_project_id): add_notice(req, _('Removed project successfully')) elif action == 'remove_expired': if arch.remove_expired(): add_notice(req, _('Removed expired projects successfully')) else: add_warning(req, _('Unknown action')) except Exception: add_warning(req, _('Failed to complete the action')) self.log.exception('Failed to {0} for project {1}'.format( action, archived_project_id)) # After post method, redirect back to listing return req.redirect(req.href('/admin/projects/prjarchive')) add_script(req, 'multiproject/js/jquery-ui.js') add_stylesheet(req, 'multiproject/css/jquery-ui.css') add_script(req, 'multiproject/js/multiproject.js') add_script(req, 'multiproject/js/admin_project_archive.js') return 'multiproject_admin_project_archive.html', { 'projects': projects }
def remove_project(self, req): """ Handler for removing project :param Request req: Trac request Handler expects to have following arguments in it: - project: Name of the project env - goto: Optional URL where to go after project removal. Defaults to /home/myprojects """ backurl = req.args.get('goto', ProjectListModule.home('myprojects')) short_name = req.args.get('project') if not short_name: return self.remove_failure(req) if req.args.get('cancel'): add_notice(req, 'Project deletion cancelled') return self.remove_failure(req) author = req.authname project = Project.get(env_name=short_name) if project is None: add_warning(req, 'Specified project does not exist!') return self.remove_failure(req) # Don't allow removing home if project.env_name == conf.sys_home_project_name: add_warning(req, 'Cannot remove home project') return self.remove_failure(req) if req.method != 'POST': return self.remove_failure(req, project=project) try: project.validate() except ProjectValidationException: req.redirect(backurl) # Check the permissions and method prjs = Projects() if ('TRAC_ADMIN' in req.perm or prjs.is_project_owner( project.env_name, author)) and req.method == 'POST': archive = ProjectArchive() # Archive the project before removal if not archive.archive(project): add_warning( req, 'Could not archive project "%s". Will not remove the project' % project.project_name) elif prjs.remove_project(project): # Notify listeners for listener in self.project_change_listeners: listener.project_deleted(project) # Notify end user add_notice(req, 'Project "%s" removed' % project.project_name) else: add_warning( req, 'Could not remove project "%s". Try again later' % project.project_name) else: add_warning( req, 'You are not allowed to remove project "%s" (check permissions and method)' % project.project_name) req.redirect(backurl)
def render_admin_panel(self, req, cat, page, path_info): """ Returns the admin view and handles the form actions """ req.perm.require('TRAC_ADMIN') project = Project.get(self.env) if req.method == 'POST': myprojects_url = conf.url_home_path + "/myprojects" conf.log.exception("Redirect URL: %s" % myprojects_url) thisurl = Href(req.base_path)(req.path_info) context = Context.from_request(req) # Handle project remove if 'remove' in req.args: # Don't allow removing home if project.env_name == conf.sys_home_project_name: add_warning(req, 'Cannot remove home project') return req.redirect(thisurl) # Archive the project before removal archive = ProjectArchive() archived = archive.archive(project) if not archived: add_warning( req, 'Could not archive project "%s". Will not remove the project' % project.project_name) return req.redirect(thisurl) # Notify listeners. The project object still exists, but database does not for listener in self.project_change_listeners: listener.project_archived(project) # Do the actual project removal projects = Projects() if projects.remove_project(project): # Notify listeners. The project object still exists, but database does not for listener in self.project_change_listeners: listener.project_deleted(project) # NOTE: We no longer have project tables/session etc available req.redirect(myprojects_url) else: add_warning( req, 'Could not remove project "%s". Try again later' % project.project_name) return req.redirect(thisurl) add_script(req, 'multiproject/js/jquery-ui.js') add_script(req, 'multiproject/js/multiproject.js') add_script(req, 'multiproject/js/admin_system.js') add_stylesheet(req, 'multiproject/css/jquery-ui.css') # NOTE: Trac automatically puts 'project' dict in chrome thus it cannot be used data = { 'multiproject': { 'project': project, 'home_url': conf.url_home_path } } return 'admin_system.html', data
class ProjectStatisticsAdminPanel(Component): """ Trac admin component for project statistics: Admin > Statistics > Projects """ implements(IAdminPanelProvider) def get_admin_panels(self, req): """ Hook into admin panel by adding the Projects -section """ if 'TRAC_ADMIN' in req.perm: yield ('statistics', _('Statistics'), 'projects', _('Projects')) def render_admin_panel(self, req, cat, page, path_info): """ Handles the admin page requests """ req.perm.require("TRAC_ADMIN") # Default values perm = 'PROJECT_VIEW' categories = [] results = [] resultsby = 'week' event_type = 'release_downloaded' maxresult_opts = [5, 10, 30, 50, 100, 0] maxresults = 10 now = datetime.utcnow() weekday, endday = calendar.monthrange(now.year, now.month) starttime = datetime(year=now.year, month=now.month, day=1, hour=0, minute=0, second=0) endtime = datetime(year=now.year, month=now.month, day=endday, hour=23, minute=59, second=59) # This ain't timemachine if endtime > now: endtime = now # Set or reset filters back to defaults if 'update' in req.args.keys(): # Try parsing the dates try: starttime = datetime.strptime(req.args.get('starttime', ''), DATEFORMATS['py']) endtime = datetime.strptime(req.args.get('endtime', ''), DATEFORMATS['py']) # Set the time to be from 00:00 -- 23:59:59 starttime = datetime( year=starttime.year, month=starttime.month, day=starttime.day, hour=0, minute=0, second=0 ) endtime = datetime( year=endtime.year, month=endtime.month, day=endtime.day, hour=23, minute=59, second=59 ) except Exception, ex: self.log.warning('Date conversion failed: %s' % ex) add_warning(req, _('Please check the time range values as they seem inappropriate. The format is: MM/DD/YY')) # Set filters # NOTE: UI allows only one category atm categories_raw = req.args.get('categories', '') if categories_raw.strip(): categories = [plaintext(categories_raw)] resultsby = req.args.get('resultsby', resultsby) # Get and check optional event type if req.args.get('event_type', '') in EVENT_DESCRIPTIONS.keys(): event_type = req.args.get('event_type', event_type) # Get and check optional max results option maxresults = req.args.get('maxresults', maxresults) if isinstance(maxresults, basestring): maxresults = int(maxresults) if maxresults.isdigit() else 10 # Fetch statistics: get project ids based on user rights and optional list of categories # NOTE: Set initial value to zero because otherwise it is considered as "fetch all" project_ids = [0] for project in Projects().get_projects_with_params(username=req.authname, perm=perm, categories=categories): project_ids.append(project.id) # Fetch project ids also from archived projects if category is not selected (archived projects no longer have one) if not categories: for archived_project in ProjectArchive().get_projects_with_params(username=req.authname, perm=perm): project_ids.append(archived_project.id) else: # Note about the archived project limitation add_warning(req, _("Archived projects are left out from statistics as they don't have category information")) # Fetch results either by week or project fetch_start = datetime.utcnow() if resultsby == 'project': results = self._get_activity_statistics_per_project(starttime, endtime, event_type, project_ids, max=maxresults) if resultsby == 'week': results = self._get_activity_statistics_per_week(starttime, endtime, event_type, project_ids, max=maxresults) self.log.info('Loaded statistics in %s msec' % (datetime.utcnow() - fetch_start).microseconds) summary = self._get_summary() # Calculate total total = sum([r['count'] for r in results]) categories_desc = ','.join(categories) if categories else 'all' self.log.info('User %s is retrieving download statistics from %d projects (categories: %s), found: %d' % (req.authname, len(project_ids), categories_desc, len(results))) # Event types, sorted by description event_types = sorted(EVENT_DESCRIPTIONS.items(), key=itemgetter(1)) # Add resources add_script(req, 'multiproject/js/jquery-ui.js') add_stylesheet(req, 'multiproject/css/jquery-ui.css') add_stylesheet(req, 'multiproject/css/statistics.css') add_script(req, 'multiproject/js/raphael.js') add_script(req, 'multiproject/js/ico.js') add_script(req, 'multiproject/js/admin_analytics_projects.js') # Set parameters to view data = { 'summary':summary, 'perm':perm, 'grouptypes': ['project', 'week'], 'categories':categories, 'resultsby':resultsby, 'starttime':starttime, 'endtime':endtime, 'event_types':event_types, 'event_type':event_type, 'event':EVENT_DESCRIPTIONS[event_type], 'dateformats':DATEFORMATS, 'results':results, 'results_json':json.dumps(results), 'total':total, 'categories_desc':categories_desc, 'maxresults':maxresults, 'maxresult_opts':maxresult_opts } return 'admin_analytics_projects.html', data