Skip to content

Commit

Permalink
Adding experienced mapper role
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre GIRAUD committed Feb 10, 2017
1 parent f20a97d commit ebb214f
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 8 deletions.
22 changes: 22 additions & 0 deletions alembic/versions/1bdc819ae210_adding_experienced_mapper_role.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Adding experienced mapper role
Revision ID: 1bdc819ae210
Revises: 4a5bf96b558d
Create Date: 2017-01-19 14:10:58.578127
"""

# revision identifiers, used by Alembic.
revision = '1bdc819ae210'
down_revision = '4a5bf96b558d'

from alembic import op
import sqlalchemy as sa


def upgrade():
op.add_column('project', sa.Column('requires_experienced_mapper_role', sa.Boolean(), nullable=True))


def downgrade():
op.drop_column('project', 'requires_experienced_mapper_role')
2 changes: 2 additions & 0 deletions osmtm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ def main(global_config, **settings):
config.add_route('user_admin', '/user/{id:\d+}/admin')
config.add_route('user_project_manager', '/user/{id:\d+}/project_manager')
config.add_route('user_validator', '/user/{id:\d+}/validator')
config.add_route('user_experienced_mapper',
'/user/{id:\d+}/experienced_mapper')
config.add_route('user_prefered_editor',
'/user/prefered_editor/{editor}', xhr=True)
config.add_route('user_prefered_language',
Expand Down
10 changes: 10 additions & 0 deletions osmtm/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class ST_SetSRID(GenericFunction):
ADMIN = 1
PROJECT_MANAGER = 2
VALIDATOR = 4
EXPERIENCED_MAPPER = 8


class User(Base):
Expand All @@ -128,6 +129,7 @@ class User(Base):
role_admin = ADMIN
role_project_manager = PROJECT_MANAGER
role_validator = VALIDATOR
role_experienced_mapper = EXPERIENCED_MAPPER
role = Column(Integer, default=0)

accepted_licenses = relationship("License", secondary=users_licenses_table)
Expand Down Expand Up @@ -156,13 +158,18 @@ def is_project_manager(self):
def is_validator(self):
return self.role & self.role_validator

@hybrid_property
def is_experienced_mapper(self):
return self.role & self.role_experienced_mapper

def as_dict(self):
return {
"id": self.id,
"username": self.username,
"is_admin": self.is_admin,
"is_project_manager": self.is_project_manager,
"is_validator": self.is_validator,
"is_experienced_mapper": self.is_experienced_mapper,
}


Expand Down Expand Up @@ -550,6 +557,9 @@ class Project(Base, Translatable):

labels = relationship("Label", secondary=project_labels_table)

# whether the validation should require the validator role or not
requires_experienced_mapper_role = Column(Boolean, default=False)

def __init__(self, name, user=None):
self.name = name
self.author = user
Expand Down
17 changes: 17 additions & 0 deletions osmtm/templates/project.edit.mako
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,23 @@ geometry = loads(str(project.area.geometry.data))
</div>
</div>
</div>
<hr>
<div class="row">
<div class="input-group">
<div class="checkbox">
<label>
<%
checked = 'checked' if project.requires_experienced_mapper_role else ''
%>
<input type="checkbox" name="requires_experienced_mapper_role" ${checked}>
${_('Only experienced mappers can contribute')}
</label>
<div class="help-block">
${_("If checked, only users with the 'experienced mapper role' will be able to contribute to the current project. If not, anyone can.")}
</div>
</div>
</div>
</div>
<%
from osmtm.models import dumps
%>
Expand Down
42 changes: 36 additions & 6 deletions osmtm/templates/task.unlocked.mako
Original file line number Diff line number Diff line change
@@ -1,26 +1,56 @@
<%
from osmtm.models import TaskState
from osmtm.mako_filters import (
markdown_filter,
)
requires_experience = user is not None and task.project.requires_experienced_mapper_role and not (user.is_experienced_mapper or user.is_admin or user.is_project_manager)
if user is not None:
user_link = request.route_url('user',username=user.username)
else:
user_link = ''
author = task.project.author.username if task.project.author else ''
%>
<div class="text-center">

This comment has been minimized.

Copy link
@aymannageeb

aymannageeb Dec 7, 2017

user_link=brok>open author username

<div>
% if locked_task is not None:
% if locked_task != task:
<%include file="task.current_locked.mako" />
% endif
% elif not task.assigned_to or task.assigned_to == user:
% if task.cur_state.state == TaskState.state_ready or task.cur_state.state == TaskState.state_invalidated:
% if requires_experience:
<%
link = 'http://www.openstreetmap.org/message/new/%s?message[title]=%s&message[body]=%s' % (
author,
_("Privileges for project {project} in the tasking manager").format(project='%23' + str(task.project_id)),
_("I would like to be granted as experienced mapper.") + "%0D%0A%0D%0A[{0}]({1})".format(
_("Link to my profile page"),
user_link)
)
%>
<p>
${_('You need to be an **experienced mapper** to contribute to this project.')|markdown_filter}
${_("You think you are an **experienced mapper**? Click [this link](${link}) to send a message to the author to ask him form permissions to work on this project.",
mapping={'link': link})| markdown_filter, n}
</p>
<hr>
% endif
% if task.cur_state.state == TaskState.state_ready or task.cur_state.state == TaskState.state_invalidated:
<p class="text-center">
<a id="lock" href="${request.route_path('task_lock', task=task.id, project=task.project_id)}"
rel="tooltip"
data-original-title="${_('Lock this task to tell others that you are currently working on it.')}"
data-container="body"
class="btn btn-success">
class="btn btn-success ${'disabled' if requires_experience else ''}">
<i class="glyphicon glyphicon-share-alt"></i>&nbsp;
${_('Start mapping')}
</a>
</p>
% elif (task.cur_state.state == TaskState.state_done or task.cur_state.state == TaskState.state_validated):
% if user == task.states[0].user:
<form action="${request.route_path('task_cancel_done', task=task.id, project=task.project_id)}" method="POST" role="form">
<form action="${request.route_path('task_cancel_done', task=task.id, project=task.project_id)}" method="POST" role="form" class-"text-center">
${_('Marked as done by mistake?')}
<button type="submit"
data-container="body"
Expand All @@ -31,12 +61,12 @@ from osmtm.models import TaskState
<hr>
% endif
% if user and (not task.project.requires_validator_role or user.is_validator):
<p>
<p class="text-center">
<a id="lock" href="${request.route_path('task_lock', task=task.id, project=task.project_id)}"
rel="tooltip"
data-original-title="${_('Lock this task to tell others that you are currently reviewing it. Validate that this task has been mapped correctly and completely.')}"
data-container="body"
class="btn btn-success">
class="btn btn-success ${'disabled' if requires_experience else ''}">
<i class="glyphicon glyphicon-thumbs-up"></i>&nbsp;
<i class="glyphicon glyphicon-thumbs-down"></i>&nbsp;
${_('Review the work')}
Expand Down
15 changes: 15 additions & 0 deletions osmtm/templates/user.mako
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,21 @@ else:
% endif
% endif
</p>
<p>
% if contributor.is_experienced_mapper:
<i class="glyphicon glyphicon-ok"></i>
${_("This user is an experienced mapper.")}
% if user is not None and (user.is_admin or user.is_project_manager) and user != contributor:
<a href="${request.route_path('user_experienced_mapper', id=contributor.id)}">${_('Remove privileges')}</a>
% endif
% else:
% if user is not None and (user.is_admin or user.is_project_manager):
<i class="glyphicon glyphicon-ok"></i>
<a href="${request.route_path('user_experienced_mapper', id=contributor.id)}">${_('Set as experienced mapper')}</a>
% endif
% endif
</p>
</div>
</div>
<div class="row">
Expand Down
10 changes: 10 additions & 0 deletions osmtm/templates/users.mako
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
% if user.is_validator:
<i class="glyphicon glyphicon-ok"></i>
% endif
% if user.is_experienced_mapper:
<i class="glyphicon glyphicon-star"></i>
% endif
</li>
% endfor
% endif
Expand Down Expand Up @@ -60,6 +63,13 @@
${_('Validator')}
</label>
</li>
<li>
<label>
<input type="checkbox" name="role" value="8" ${'checked' if u'8' in request.params.getall('role') else ''}>
<i class="glyphicon glyphicon-star"></i>
${_('Experienced mapper')}
</label>
</li>
</ul>
</form>
</small>
Expand Down
5 changes: 5 additions & 0 deletions osmtm/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
ADMIN_USER_ID = 3
PROJECT_MANAGER_USER_ID = 4
VALIDATOR_ID = 5
EXPERIENCED_MAPPER_ID = 6

translation_manager.options.update({
'locales': ['en', 'fr'],
Expand Down Expand Up @@ -67,6 +68,10 @@ def populate_db():
user.role = User.role_validator
DBSession.add(user)

user = User(EXPERIENCED_MAPPER_ID, u'user_experienced_mapper')
user.role = User.role_experienced_mapper
DBSession.add(user)

license = License()
license.name = u'LicenseBar'
license.description = u'the_description_for_license_bar'
Expand Down
28 changes: 27 additions & 1 deletion osmtm/tests/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ def test_project_users(self):

res = self.testapp.get('/project/%d/users' % project_id,
status=200, xhr=True)
self.assertEqual(len(res.json), 5)
self.assertEqual(len(res.json), 6)

res = self.testapp.get('/project/%d/users?q=pro' % project_id,
status=200, xhr=True)
Expand Down Expand Up @@ -1063,3 +1063,29 @@ def test_home__search_label(self):
})
projects = res.html.select('.project')
self.assertEqual(len(projects), 0)

def test_project__experienced_mapper(self):
import transaction
from osmtm.models import DBSession, Project
project_id = self.create_project()
project = DBSession.query(Project).get(project_id)
project.requires_experienced_mapper_role = True
DBSession.add(project)
DBSession.flush()
transaction.commit()

project = DBSession.query(Project).get(project_id)
tasks = project.tasks
headers_user1 = self.login_as_user1()
from osmtm.tests import EXPERIENCED_MAPPER_ID
headers_exp_map = self.login_as_user(EXPERIENCED_MAPPER_ID)

res = self.testapp.get('/project/%d/task/%d' % (project_id,
tasks[0].id),
headers=headers_user1, status=200, xhr=True)
self.assertTrue('experienced mapper' in res.body)

res = self.testapp.get('/project/%d/task/%d' % (project_id,
tasks[0].id),
headers=headers_exp_map, status=200, xhr=True)
self.assertFalse('experienced mapper' in res.body)
2 changes: 1 addition & 1 deletion osmtm/tests/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def test_users__logged_in(self):

def test_users_json(self):
res = self.testapp.get('/users.json', status=200)
self.assertEqual(len(res.json), 6)
self.assertEqual(len(res.json), 7)

def test_users_json__query(self):
res = self.testapp.get('/users.json',
Expand Down
4 changes: 4 additions & 0 deletions osmtm/views/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,10 @@ def project_edit(request):
('requires_validator_role' in request.params and
request.params['requires_validator_role'] == 'on')

project.requires_experienced_mapper_role = \
('requires_experienced_mapper_role' in request.params and
request.params['requires_experienced_mapper_role'] == 'on')

project.status = request.params['status']
project.priority = request.params['priority']

Expand Down
12 changes: 12 additions & 0 deletions osmtm/views/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@ def user_validator(request):
username=user.username))


@view_config(route_name='user_experienced_mapper', permission="user_edit")
def user_experienced_mapper(request):
id = request.matchdict['id']
user = DBSession.query(User).get(id)

user.role ^= User.role_experienced_mapper
DBSession.flush()

return HTTPFound(location=route_path("user", request,
username=user.username))


@view_config(route_name='user', renderer='user.mako')
def user(request):

Expand Down

0 comments on commit ebb214f

Please sign in to comment.