Example #1
0
def promote(request):
    """ Promote a user to a product owner or scrum master.
        The permissions are updated for this user accordingly.
    """
    if not request.user.is_superuser():
        return error_response(_('Permission denied'))
    uid = request.REQUEST.get('uid')
    usr = get_object_or_404(User, pk=uid)
    staff = usr.get_profile()
    role = request.REQUEST.get('role', '')
    if role not in ['D','M','O']:
        return error_response(_('Invalid role'))
    staff.role = role
    staff.save()
    # change permission
    # product owner permissions: add,change,delete product, backlog, releaseplan
    # scrum master permissions: add,change,delete backlog, sprint, task, releaseplan
    if role == 'D':
        usr.permissions.clear()
    else:
        perms = {'O':['product','backlog','releaseplan'],'M':['sprint','backlog','releaseplan']}
        for p in perms[role]:
            for act in ['add','change','delete']:
                cname = '%s_%s' % (act, p)
                usr.permissions.add(Permission.objects.get(codename=cname))
    return HttpResponseRedirect('/')
Example #2
0
def start(request):
    """ Start a new voting session.
        @return: {"sid":"a343545d4454.."}
    """
    usr = request.user
    pid = request.GET.get('pid', None)
    if not pid:
        return error_response(_('No Product ID'), fmt='json')
    if not is_scrum_master(request, pid):
        return error_response(_('Scrum Master required'), fmt='json')
    return json_response(Vote.objects.start(usr, pid))
Example #3
0
def start(request):
    """ Start a new voting session.
        @return: {"sid":"a343545d4454.."}
    """
    usr = request.user
    pid = request.GET.get("pid", None)
    if not pid:
        return error_response(_("No Product ID"), fmt="json")
    if not is_scrum_master(request, pid):
        return error_response(_("Scrum Master required"), fmt="json")
    return json_response(Vote.objects.start(usr, pid))
Example #4
0
def remove_task(request, tid):
    """ Remove a task from Task.
        User permission required: delete_backlog
    """
    if not tid:
        tid = request.REQUEST.get('tid', None)
        if not tid:
            return render(request, 'error', {'err':_('No task ID')})
    task = get_object_or_404(Task, pk=tid)
    if not task.item.product.owner_or_master(request.user):
        return error_response(_('Permision denied'))
    try:
        task.delete()
        return HttpResponseRedirect('/backlog/%s/tasks'%task.item.pk)
    except:
        return error_response(_('Error deleting task'))
Example #5
0
def status(request):
    """ Check status of voting and get sid if started.
    """
    pid = request.GET.get("pid", None)
    if not pid:
        return error_response(_("No Product ID"), fmt="json")
    return json_response(Vote.objects.status(pid))
Example #6
0
def submit_retro(request):
    """ The scrum master submits the retrospectives for the sprint review.
        request.path: /sprint/retro/submit
        This is done through Ajax call and pass data in JSON.
        User permission: change_sprint
    """
    if request.method == 'POST':
        good = request.POST.get('good', '')
        bad = request.POST.get('bad', '')
        advice = request.POST.get('next', '')
        sid = request.POST.get('sid')
        try:
            sp = Sprint.objects.get(pk=sid)
            if sp.master != request.user:
                return render(request,
                              'error', {'err': _('Permission denied')},
                              fmt='json')
            sp.retro = '{"good":"%s","bad":"%s","next":"%s"}' % (
                jsonstr(good), jsonstr(bad), jsonstr(advice))
            sp.save()
            return HttpResponse('{"status":"OK"}')
        except Exception, e:
            logger.error('submit_retro failed: %s' % e)
            return error_response(_('Error saving submits, retry later.'),
                                  fmt='json')
Example #7
0
def status(request):
    """ Check status of voting and get sid if started.
    """
    pid = request.GET.get('pid', None)
    if not pid:
        return error_response(_('No Product ID'), fmt='json')
    return json_response(Vote.objects.status(pid))
Example #8
0
def remove_task(request, tid):
    """ Remove a task from Task.
        User permission required: delete_backlog
    """
    if not tid:
        tid = request.REQUEST.get('tid', None)
        if not tid:
            return render(request, 'error', {'err': _('No task ID')})
    task = get_object_or_404(Task, pk=tid)
    if not task.item.product.owner_or_master(request.user):
        return error_response(_('Permision denied'))
    try:
        task.delete()
        return HttpResponseRedirect('/backlog/%s/tasks' % task.item.pk)
    except:
        return error_response(_('Error deleting task'))
Example #9
0
def vote(request):
    """ Submit a value for the voting session.
    """
    try:
        sid, pid, vote = get_params(request, ['sid', 'pid', 'vote'])
    except KeyError, e:
        logger.error('poker.vote() request.get error: %s' % e)
        return error_response(_('Not enough parameters'), fmt='json')
Example #10
0
def stop(request):
    """ Stop the session.
    """
    try:
        sid, pid = get_params(request, ['sid', 'pid'])
    except KeyError, e:
        logger.error('poker.stop() error: %s' % e)
        return error_response(_('Not enough parameters'), fmt='json')
Example #11
0
def stop(request):
    """ Stop the session.
    """
    try:
        sid, pid = get_params(request, ["sid", "pid"])
    except KeyError, e:
        logger.error("poker.stop() error: %s" % e)
        return error_response(_("Not enough parameters"), fmt="json")
Example #12
0
def vote(request):
    """ Submit a value for the voting session.
    """
    try:
        sid, pid, vote = get_params(request, ["sid", "pid", "vote"])
    except KeyError, e:
        logger.error("poker.vote() request.get error: %s" % e)
        return error_response(_("Not enough parameters"), fmt="json")
Example #13
0
def unpick_task(request, tid=None):
    """ Delevepor unselect a task and put it back to the unassigned status.
    """
    if not tid:
        tid = request.REQUEST.get('tid', None)
    task = get_object_or_404(Task, pk=tid)
    if not task.doer:
        logger.error('unpick_task(tid=%s), task.doer is None' % tid)
        return error_response(_('Task not assigned to anybody'))
    if task.doer != request.user:
        logger.warning('unpick_task(tid=%s), task.doer != request.user' % tid)
        return error_response(_('Not task doer'))
    try:
        task.unassign(request.user)
        return HttpResponseRedirect('/daily')
    except Exception, e:
        logger.error('unpick_task.save() failed: %s' % e)
        return error_response(_('Failed to save, retry later.'))
Example #14
0
def collect(request):
    """ Collect all submitted votes.
        @return: {"status":"STARTED","votes":{"<uid>":"<vote>","1":3,..}}
    """
    try:
        sid, pid = get_params(request, ["sid", "pid"])
    except KeyError, e:
        logger.error("poker.collect() error: %s" % e)
        return error_response(_("Not enough parameters"), fmt="json")
Example #15
0
def collect(request):
    """ Collect all submitted votes.
        @return: {"status":"STARTED","votes":{"<uid>":"<vote>","1":3,..}}
    """
    try:
        sid, pid = get_params(request, ['sid', 'pid'])
    except KeyError, e:
        logger.error('poker.collect() error: %s' % e)
        return error_response(_('Not enough parameters'), fmt='json')
Example #16
0
def unpick_task(request, tid=None):
    """ Delevepor unselect a task and put it back to the unassigned status.
    """
    if not tid:
        tid = request.REQUEST.get("tid", None)
    task = get_object_or_404(Task, pk=tid)
    if not task.doer:
        logger.error("unpick_task(tid=%s), task.doer is None" % tid)
        return error_response(_("Task not assigned to anybody"))
    if task.doer != request.user:
        logger.warning("unpick_task(tid=%s), task.doer != request.user" % tid)
        return error_response(_("Not task doer"))
    try:
        task.unassign(request.user)
        return HttpResponseRedirect("/daily")
    except Exception, e:
        logger.error("unpick_task.save() failed: %s" % e)
        return error_response(_("Failed to save, retry later."))
Example #17
0
def import_stories(request):
    """ Upload a CSV file as stories into the specified product backlog.
        A list of fields can be selected to parse the rows in the CSV to match the Backlog metadata.
    """
    # TODO: implement importing backlog items from a CSV file from upload
    if request.method == 'POST':
        pass
    else:
        pass
    return error_response(_('Not implemented yet'))
Example #18
0
def import_stories(request):
    """ Upload a CSV file as stories into the specified product backlog.
        A list of fields can be selected to parse the rows in the CSV to match the Backlog metadata.
    """
    # TODO: implement importing backlog items from a CSV file from upload
    if request.method == 'POST':
        pass
    else:
        pass
    return error_response(_('Not implemented yet'))
Example #19
0
def include_backlog(request, sid, bid):
    """ Include a backlog item into this sprint.
        If this item is assigned to another sprint, returns an error.
        User permission: change_sprint and must be scrum master of the sprint.
    """
    try:
        bitem = get_object_or_404(Backlog, pk=bid)
        if bitem.sprint:
            logger.error('include_backlog(sid=%s,bid=%s), item already assigned to %s'%bitem.sprint)
            return error_response(_('This item is already assigned to another sprint'))
        sprint = get_object_or_404(Sprint, pk=sid)
        if sprint.master != request.user:
            logger.error('include_backlog() user Not sprint master')
            return error_response(_('Permission denied'))
        bitem.sprint = sprint
        bitem.save()
    except Exception, e:
        logger.error('include_backlog(sid=%s,bid=%s) failed:%s' % (sid,bid,e))
        return error_response(_('Error saving backlog item in the sprint.'))
Example #20
0
def pick_task(request, tid=None):
    """ A team member picks a task to work on. This is an Ajax call.
        There should be a way to notify others that somebody picked a task.
        A simple way is to save this operation in a database table, and others
        using the same page will check it up and once applied will put a mark there
        so as not to repeat it. This can be done using a timestamp. Operations with timestamp
        later than the last visit time, will be applied, or else ignored.
    """
    if not tid:
        tid = request.REQUEST.get("tid", None)
    if tid:
        task = get_object_or_404(Task, pk=tid)
    else:
        logger.error("pick_task tid not given")
        return error_response(_("Task ID error"))
    if task.doer:
        return error_response(_("This task has been assigned to another member."))
    try:
        task.assign(request.user)
    except Exception, e:
        logger.error("pick_task save() failed: %s" % e)
        return error_response(_("Failed to save, retry later."))
Example #21
0
def save_estimate(request, tid):
    """ Get or Post/save Backlog(item).estimate. Only product scrum master can save.
        Query path: /task/<tid>/estimate[?est=4]
        User permission required: change_backlog
    """
    try:
        tsk = Task.objects.get(pk=tid)
    except Task.DoesNotExist:
        return error_response(_('Task not found'), fmt='json')
    
    if request.method == 'GET':
        return HttpResponse('{"status":"OK","estimate":"%s"}' % (tsk.estimate))
    else:
        # TODO: verify user is a product owner or scrum master
        tsk.estimate = float(request.POST.get('est'))
        try:
            tsk.save()
            # TODO: call Backlog.update_estimate to sum up all task estimates
            return HttpResponseRedirect('/backlog/%s/tasks'%tsk.item.pk)
#            return HttpResponse('{"status":"OK"}')
        except:
            return error_response(_('Failed to save task estimate.'))
Example #22
0
def include_backlog(request, sid, bid):
    """ Include a backlog item into this sprint.
        If this item is assigned to another sprint, returns an error.
        User permission: change_sprint and must be scrum master of the sprint.
    """
    try:
        bitem = get_object_or_404(Backlog, pk=bid)
        if bitem.sprint:
            logger.error(
                'include_backlog(sid=%s,bid=%s), item already assigned to %s' %
                bitem.sprint)
            return error_response(
                _('This item is already assigned to another sprint'))
        sprint = get_object_or_404(Sprint, pk=sid)
        if sprint.master != request.user:
            logger.error('include_backlog() user Not sprint master')
            return error_response(_('Permission denied'))
        bitem.sprint = sprint
        bitem.save()
    except Exception, e:
        logger.error('include_backlog(sid=%s,bid=%s) failed:%s' %
                     (sid, bid, e))
        return error_response(_('Error saving backlog item in the sprint.'))
Example #23
0
def pick_task(request, tid=None):
    """ A team member picks a task to work on. This is an Ajax call.
        There should be a way to notify others that somebody picked a task.
        A simple way is to save this operation in a database table, and others
        using the same page will check it up and once applied will put a mark there
        so as not to repeat it. This can be done using a timestamp. Operations with timestamp
        later than the last visit time, will be applied, or else ignored.
    """
    if not tid:
        tid = request.REQUEST.get('tid', None)
    if tid:
        task = get_object_or_404(Task, pk=tid)
    else:
        logger.error('pick_task tid not given')
        return error_response(_('Task ID error'))
    if task.doer:
        return error_response(
            _('This task has been assigned to another member.'))
    try:
        task.assign(request.user)
    except Exception, e:
        logger.error('pick_task save() failed: %s' % e)
        return error_response(_('Failed to save, retry later.'))
Example #24
0
def save_estimate(request, tid):
    """ Get or Post/save Backlog(item).estimate. Only product scrum master can save.
        Query path: /task/<tid>/estimate[?est=4]
        User permission required: change_backlog
    """
    try:
        tsk = Task.objects.get(pk=tid)
    except Task.DoesNotExist:
        return error_response(_('Task not found'), fmt='json')

    if request.method == 'GET':
        return HttpResponse('{"status":"OK","estimate":"%s"}' % (tsk.estimate))
    else:
        # TODO: verify user is a product owner or scrum master
        tsk.estimate = float(request.POST.get('est'))
        try:
            tsk.save()
            # TODO: call Backlog.update_estimate to sum up all task estimates
            return HttpResponseRedirect('/backlog/%s/tasks' % tsk.item.pk)


#            return HttpResponse('{"status":"OK"}')
        except:
            return error_response(_('Failed to save task estimate.'))
Example #25
0
def planning_poker(request, tid=None):
    """ Start planning poker page for backlog task tid.
        User permission: developer
    """
    if not tid:
        tid = request.REQUEST.get('tid', None)
        if not tid:
            return error_response(_('No task specified'))
    task = get_object_or_404(Task, pk=tid)
    item = task.item
    product = item.product
    if not product.has_member(request.user):
        return render(request, 'error', {'err':_('Permission denied')})
    params = {'product':product,'backlog':item,'task':task,'master':product.owner_or_master(request.user)}
    return render(request, 'poker', params,'backlog/')
Example #26
0
def save_notes(request):
    """ The scrum master saves some notes about a backlog item.
        User permission required: change_backlog
    """
    if request.method=='POST':
        itemid = request.POST.get('item',None)
        notes = request.POST.get('notes','')
        try:
            item = Backlog.objects.get(pk=itemid)
            if request.user not in [item.product.owner, item.product.master]:
                logger.warning('Not scrum master or product owner')
                return render(request, 'error', {'err':_('Permission denied')})
            item.notes = notes
            item.save()
            return HttpResponse('{"status":"OK"}')
        except Exception,e:
            logger.exception('save_notes error: %s'%e)
            return error_response(_('Error saving notes'))
Example #27
0
def save_notes(request):
    """ The scrum master saves some notes about a backlog item.
        User permission required: change_backlog
    """
    if request.method == 'POST':
        itemid = request.POST.get('item', None)
        notes = request.POST.get('notes', '')
        try:
            item = Backlog.objects.get(pk=itemid)
            if request.user not in [item.product.owner, item.product.master]:
                logger.warning('Not scrum master or product owner')
                return render(request, 'error',
                              {'err': _('Permission denied')})
            item.notes = notes
            item.save()
            return HttpResponse('{"status":"OK"}')
        except Exception, e:
            logger.exception('save_notes error: %s' % e)
            return error_response(_('Error saving notes'))
Example #28
0
def planning_poker(request, tid=None):
    """ Start planning poker page for backlog task tid.
        User permission: developer
    """
    if not tid:
        tid = request.REQUEST.get('tid', None)
        if not tid:
            return error_response(_('No task specified'))
    task = get_object_or_404(Task, pk=tid)
    item = task.item
    product = item.product
    if not product.has_member(request.user):
        return render(request, 'error', {'err': _('Permission denied')})
    params = {
        'product': product,
        'backlog': item,
        'task': task,
        'master': product.owner_or_master(request.user)
    }
    return render(request, 'poker', params, 'backlog/')
Example #29
0
def submit_retro(request):
    """ The scrum master submits the retrospectives for the sprint review.
        request.path: /sprint/retro/submit
        This is done through Ajax call and pass data in JSON.
        User permission: change_sprint
    """
    if request.method == 'POST':
        good = request.POST.get('good','')
        bad = request.POST.get('bad','')
        advice = request.POST.get('next','')
        sid = request.POST.get('sid')
        try:
            sp = Sprint.objects.get(pk=sid)
            if sp.master != request.user: 
                return render(request, 'error', {'err':_('Permission denied')}, fmt='json')
            sp.retro = '{"good":"%s","bad":"%s","next":"%s"}' % (jsonstr(good), jsonstr(bad), jsonstr(advice))
            sp.save()
            return HttpResponse('{"status":"OK"}')
        except Exception,e:
            logger.error('submit_retro failed: %s' % e)
            return error_response(_('Error saving submits, retry later.'), fmt='json')
Example #30
0

@permission_required('sprint.change_sprint')
def submit_retro(request):
    """ The scrum master submits the retrospectives for the sprint review.
        request.path: /sprint/retro/submit
        This is done through Ajax call and pass data in JSON.
        User permission: change_sprint
    """
    if request.method == 'POST':
        good = request.POST.get('good', '')
        bad = request.POST.get('bad', '')
        advice = request.POST.get('next', '')
        sid = request.POST.get('sid')
        try:
            sp = Sprint.objects.get(pk=sid)
            if sp.master != request.user:
                return render(request,
                              'error', {'err': _('Permission denied')},
                              fmt='json')
            sp.retro = '{"good":"%s","bad":"%s","next":"%s"}' % (
                jsonstr(good), jsonstr(bad), jsonstr(advice))
            sp.save()
            return HttpResponse('{"status":"OK"}')
        except Exception, e:
            logger.error('submit_retro failed: %s' % e)
            return error_response(_('Error saving submits, retry later.'),
                                  fmt='json')
    else:
        return error_response(_('POST only'))
Example #31
0
def export_stories(request):
    """ Download backlog items as CSV file
    """
    # TODO: implement exporting backlog items as a CSV file for download
    return error_response(_('Not implemented yet'))
Example #32
0
def jsonstr(st):
    """ Convert double quote marks into HTML encoding &quot;
    """
    return st.replace('"', '&quot;')

@permission_required('sprint.change_sprint')
def submit_retro(request):
    """ The scrum master submits the retrospectives for the sprint review.
        request.path: /sprint/retro/submit
        This is done through Ajax call and pass data in JSON.
        User permission: change_sprint
    """
    if request.method == 'POST':
        good = request.POST.get('good','')
        bad = request.POST.get('bad','')
        advice = request.POST.get('next','')
        sid = request.POST.get('sid')
        try:
            sp = Sprint.objects.get(pk=sid)
            if sp.master != request.user: 
                return render(request, 'error', {'err':_('Permission denied')}, fmt='json')
            sp.retro = '{"good":"%s","bad":"%s","next":"%s"}' % (jsonstr(good), jsonstr(bad), jsonstr(advice))
            sp.save()
            return HttpResponse('{"status":"OK"}')
        except Exception,e:
            logger.error('submit_retro failed: %s' % e)
            return error_response(_('Error saving submits, retry later.'), fmt='json')
    else:
        return error_response(_('POST only'))
        
Example #33
0
        return error_response(_("No Product ID"), fmt="json")
    return json_response(Vote.objects.status(pid))


@login_required
def vote(request):
    """ Submit a value for the voting session.
    """
    try:
        sid, pid, vote = get_params(request, ["sid", "pid", "vote"])
    except KeyError, e:
        logger.error("poker.vote() request.get error: %s" % e)
        return error_response(_("Not enough parameters"), fmt="json")

    if not is_team_member(request, pid):
        return error_response(_("Team member required"), fmt="json")

    v, created = Vote.objects.get_or_create(session=sid, product=pid, voter=request.user)
    try:
        v.vote = vote
        v.save()
        return HttpResponse('{"status":"OK"}', content_type="application/json")
    except Exception, e:
        logger.error("poker.vote() error: %s" % e)
        return error_response(_("Error saving your vote"), fmt="json")


@login_required
def collect(request):
    """ Collect all submitted votes.
        @return: {"status":"STARTED","votes":{"<uid>":"<vote>","1":3,..}}
Example #34
0
def export_stories(request):
    """ Download backlog items as CSV file
    """
    # TODO: implement exporting backlog items as a CSV file for download
    return error_response(_('Not implemented yet'))
Example #35
0
        return error_response(_('No Product ID'), fmt='json')
    return json_response(Vote.objects.status(pid))


@login_required
def vote(request):
    """ Submit a value for the voting session.
    """
    try:
        sid, pid, vote = get_params(request, ['sid', 'pid', 'vote'])
    except KeyError, e:
        logger.error('poker.vote() request.get error: %s' % e)
        return error_response(_('Not enough parameters'), fmt='json')

    if not is_team_member(request, pid):
        return error_response(_('Team member required'), fmt='json')

    v, created = Vote.objects.get_or_create(session=sid,
                                            product=pid,
                                            voter=request.user)
    try:
        v.vote = vote
        v.save()
        return HttpResponse('{"status":"OK"}', content_type='application/json')
    except Exception, e:
        logger.error('poker.vote() error: %s' % e)
        return error_response(_('Error saving your vote'), fmt='json')


@login_required
def collect(request):