blob: 63819c3c224b88443cda39280f965325bd4fe33f [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from __future__ import unicode_literals
from __future__ import absolute_import
import logging
from tg import tmpl_context as c
from datetime import datetime
from allura.app import Application, SitemapEntry
from allura.lib import helpers as h
from allura import model as M
from allura.eventslistener import EventsListener
from .model.stats import UserStats
from .controllers.userstats import ForgeUserStatsController
from forgeuserstats import version
from ming.orm import session
log = logging.getLogger(__name__)
class UserStatsListener(EventsListener):
def newArtifact(self, art_type, art_datetime, project, user):
stats = user.stats
if not stats:
stats = UserStats.create(user)
stats.addNewArtifact(art_type, art_datetime, project)
def modifiedArtifact(self, art_type, art_datetime, project, user):
stats = user.stats
if not stats:
stats = UserStats.create(user)
stats.addModifiedArtifact(art_type, art_datetime, project)
def newUser(self, user):
UserStats.create(user)
def ticketEvent(self, event_type, ticket, project, user):
if user is None:
return
stats = user.stats
if not stats:
stats = UserStats.create(user)
if event_type == "assigned":
stats.addAssignedTicket(ticket.mod_date, project)
elif event_type == "revoked":
stats.addRevokedTicket(ticket.mod_date, project)
elif event_type == "closed":
stats.addClosedTicket(
ticket.created_date, ticket.mod_date, project)
def newCommit(self, newcommit, project, user):
stats = user.stats
if not stats:
stats = UserStats.create(user)
stats.addCommit(newcommit, datetime.utcnow(), project)
def addUserLogin(self, user):
stats = user.stats
if not stats:
stats = UserStats.create(user)
stats.addLogin(datetime.utcnow())
def newOrganization(self, organization):
pass
class ForgeUserStatsApp(Application):
__version__ = version.__version__
tool_label = 'UserStats'
default_mount_label = 'Stats'
default_mount_point = 'stats'
permissions = ['configure', 'read', 'write',
'unmoderated_post', 'post', 'moderate', 'admin']
permissions_desc = {
'read': 'View user stats.',
'admin': 'Toggle stats visibility.',
}
max_instances = 0
has_notifications = False
ordinal = 15
config_options = Application.config_options
default_external_feeds = []
icons = {
24: 'userstats/images/stats_24.png',
32: 'userstats/images/stats_32.png',
48: 'userstats/images/stats_48.png'
}
root = ForgeUserStatsController()
def __init__(self, project, config):
Application.__init__(self, project, config)
role_admin = M.ProjectRole.by_name('Admin', project)._id
role_anon = M.ProjectRole.by_name('*anonymous', project)._id
self.config.acl = [
M.ACE.allow(role_anon, 'read'),
M.ACE.allow(role_admin, 'admin')]
def main_menu(self):
return [SitemapEntry(self.config.options.mount_label, '.')]
def is_visible_to(self, user):
# we don't work with user subprojects
return c.project.is_root
@property
@h.exceptionless([], log)
def sitemap(self):
menu_id = self.config.options.mount_label
with h.push_config(c, app=self):
return [
SitemapEntry(menu_id, '.')[self.sidebar_menu()]]
@property
def show_discussion(self):
if 'show_discussion' in self.config.options:
return self.config.options['show_discussion']
else:
return True
@h.exceptionless([], log)
def sidebar_menu(self):
base = c.app.url
links = [SitemapEntry('Overview', base),
SitemapEntry('Commits', base + 'commits'),
SitemapEntry('Artifacts', base + 'artifacts'),
SitemapEntry('Tickets', base + 'tickets')]
return links
def admin_menu(self):
links = [SitemapEntry(
'Settings', c.project.url() + 'userstats/settings')]
return links
def install(self, project):
# It doesn't make any sense to install the tool twice on the same
# project therefore, if it already exists, it doesn't install it
# a second time.
for tool in project.app_configs:
if tool.tool_name == 'userstats':
if self.config.options.mount_point != tool.options.mount_point:
project.uninstall_app(self.config.options.mount_point)
return
def uninstall(self, project):
self.config.delete()
session(self.config).flush()