You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2016/01/08 19:02:32 UTC
[02/10] allura git commit: [#8024] ticket:872 Add, edit,
remove for site notifications
[#8024] ticket:872 Add, edit, remove for site notifications
* Add controller for Adding, editing and deleting SiteNotifications,
* Add templates for this cntrollers
* Edit link in site_admin_site_notifications_list
* Add tests
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/454565e6
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/454565e6
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/454565e6
Branch: refs/heads/master
Commit: 454565e69a2fd5d6529e925289c9350caade5d05
Parents: ea39da6
Author: Denis Kotov <de...@gmail.com>
Authored: Fri Dec 11 14:43:51 2015 +0200
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Fri Jan 8 12:18:11 2016 -0500
----------------------------------------------------------------------
Allura/allura/controllers/site_admin.py | 73 ++++++++++++
Allura/allura/lib/validators.py | 9 ++
.../site_admin_site_notifications_edit.html | 118 +++++++++++++++++++
.../site_admin_site_notifications_list.html | 6 +-
.../site_admin_site_notifications_new.html | 118 +++++++++++++++++++
.../allura/tests/functional/test_site_admin.py | 115 ++++++++++++++++++
6 files changed, 436 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/454565e6/Allura/allura/controllers/site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index ca45c46..878e9aa 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -30,6 +30,7 @@ from pylons import tmpl_context as c
from pylons import request
from formencode import validators, Invalid
from webob.exc import HTTPNotFound, HTTPFound
+from ming.odm import ThreadLocalORMSession
from allura.app import SitemapEntry
from allura.lib import helpers as h
@@ -422,6 +423,14 @@ class DeleteProjectsController(object):
class SiteNotificationController(object):
+ def __init__(self, note=None):
+ self.note = note
+
+ @expose()
+ def _lookup(self, id, *remainder):
+ note = M.notification.SiteNotification.query.get(_id=bson.ObjectId(id))
+ return SiteNotificationController(note=note), remainder
+
def _check_security(self):
with h.push_context(config.get('site_admin_project', 'allura'),
neighborhood=config.get('site_admin_project_nbhd', 'Projects')):
@@ -446,6 +455,63 @@ class SiteNotificationController(object):
'limit': limit
}
+ @expose('jinja:allura:templates/site_admin_site_notifications_new.html')
+ @without_trailing_slash
+ def new(self, **kw):
+ """Render the New SiteNotification form"""
+ return dict(
+ form_errors=c.form_errors or {},
+ form_values=c.form_values or {},
+ )
+
+ @expose()
+ @require_post()
+ @validate(v.CreateSiteNotificationSchema(), error_handler=new)
+ def create(self, active, impressions, content, user_role, page_regex, page_tool_type):
+ """Post a new note"""
+ M.notification.SiteNotification(
+ active=active, impressions=impressions, content=content,
+ user_role=user_role, page_regex=page_regex,
+ page_tool_type=page_tool_type)
+ ThreadLocalORMSession().flush_all()
+ redirect('../site_notifications')
+
+ @expose('jinja:allura:templates/site_admin_site_notifications_edit.html')
+ def edit(self):
+ if c.form_values:
+ return dict(
+ form_errors=c.form_errors or {},
+ form_values=c.form_values or {},
+ )
+ form_value = {}
+ form_value['active'] = str(self.note.active)
+ form_value['imressions'] = self.note.impressions
+ form_value['content'] = self.note.content
+ form_value['user_role'] = self.note.user_role if self.note.user_role is not None else ''
+ form_value['page_regex'] = self.note.page_regex if self.note.page_regex is not None else ''
+ form_value['page_tool_type'] = self.note.page_tool_type if self.note.page_tool_type is not None else ''
+ return dict(form_errors={},
+ form_values=form_value)
+
+ @expose()
+ @require_post()
+ @validate(v.CreateSiteNotificationSchema(), error_handler=edit)
+ def update(self, active=True, impressions=0, content='', user_role=None, page_regex=None, page_tool_type=None):
+ self.note.active = active
+ self.note.impressions = impressions
+ self.note.content = content
+ self.note.user_role = user_role
+ self.note.page_regex = page_regex
+ self.note.page_tool_type = page_tool_type
+ ThreadLocalORMSession().flush_all()
+ redirect('..')
+
+ @expose()
+ def delete(self):
+ self.note.delete()
+ ThreadLocalORMSession().flush_all()
+ redirect(request.referer)
+
class TaskManagerController(object):
@@ -692,3 +758,10 @@ class StatsSiteAdminExtension(SiteAdminExtension):
def update_sidebar_menu(self, links):
links.append(SitemapEntry('Stats', '/nf/admin/stats',
ui_icon=g.icons['stats']))
+
+
+class SNEditC(object):
+ @expose()
+ @with_trailing_slash
+ def _default(self, *args, **kwargs):
+ redirect('/')
http://git-wip-us.apache.org/repos/asf/allura/blob/454565e6/Allura/allura/lib/validators.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/validators.py b/Allura/allura/lib/validators.py
index 344af39..1f2bf6a 100644
--- a/Allura/allura/lib/validators.py
+++ b/Allura/allura/lib/validators.py
@@ -306,6 +306,15 @@ class CreateTaskSchema(fe.Schema):
path = PathValidator(strip=True, if_missing={}, if_empty={})
+class CreateSiteNotificationSchema(fe.Schema):
+ active = fev.StringBool()
+ impressions = fev.Int(not_empty=True)
+ content = fev.NotEmpty(messages=dict(empty='Please enter a value'))
+ user_role = fev.FancyValidator(not_empty=False, if_empty=None)
+ page_regex = fev.FancyValidator(not_empty=False, if_empty=None)
+ page_tool_type = fev.FancyValidator(not_empty=False, if_empty=None)
+
+
class DateValidator(fev.FancyValidator):
def _to_python(self, value, state):
http://git-wip-us.apache.org/repos/asf/allura/blob/454565e6/Allura/allura/templates/site_admin_site_notifications_edit.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/site_admin_site_notifications_edit.html b/Allura/allura/templates/site_admin_site_notifications_edit.html
new file mode 100644
index 0000000..07dc916
--- /dev/null
+++ b/Allura/allura/templates/site_admin_site_notifications_edit.html
@@ -0,0 +1,118 @@
+{#-
+ 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.
+-#}
+{% set page="task_manager" %}
+{% set sidebar_rel = '../' %}
+{% extends 'allura:templates/site_admin.html' %}
+
+{% block extra_css %}
+<style>
+ form {
+ margin: 1em;
+ }
+ form > div {
+ margin-bottom: 1em;
+ }
+ form > div > *{
+ display: inline-block;
+ vertical-align: top;
+ }
+ form > div input,
+ form > div textarea,
+ form > div select,
+ form > .input {
+ display: block;
+ width: 300px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ }
+ form > div label {
+ width: 100px;
+ }
+ .error {
+ width: 300px;
+ background: none;
+ border: none;
+ color: #f00;
+ margin: 0;
+ padding: 0 0 0 .8em;
+ }
+</style>
+{% endblock %}
+
+{% macro error(field) %}
+ {% if form_errors.get(field) %}
+ <span class="error">{{form_errors.get(field)}}</span>
+ {% endif %}
+{% endmacro %}
+
+{% block content %}
+<h2>Edit Site Notification</h2>
+<form method="POST" action="update" id="editnote">
+ <div>
+ <label>Active</label>
+ <div class="input">
+ <select name="active">
+ <option value="False">No</option>
+ <option value="True" {%- if form_values.get('active') == 'True' -%}selected{%- endif -%}>Yes</option>
+ </select>
+ </div>
+ {{error('active')}}
+ </div>
+ <div>
+ <label>Impressions</label>
+ <div class="input">
+ <input name="impressions" value="{{form_values.get('impressions', '0')}}" />
+ </div>
+ {{error('impressions')}}
+ </div>
+ <div>
+ <label>Content</label>
+ <div class="input">
+ <textarea name="content" rows="4">{{form_values.get('content', '')}}</textarea>
+ </div>
+ {{error('content')}}
+ </div>
+ <div>
+ <label>User Role</label>
+ <div class="input">
+ <input name="user_role" value="{{form_values.get('user_role', '')}}" />
+ </div>
+ {{error('user_role')}}
+ </div>
+ <div>
+ <label>Page Regex</label>
+ <div class="input">
+ <input name="page_regex" value="{{form_values.get('page_regex', '')}}" />
+ </div>
+ {{error('page_regex')}}
+ </div>
+ <div>
+ <label>Page Type</label>
+ <div class="input">
+ <input name="page_tool_type" value="{{form_values.get('page_tool_type', '')}}" />
+ </div>
+ {{error('page_tool_type')}}
+ </div>
+
+
+ <input type="submit" value="Save"/><br/>
+ {{lib.csrf_token()}}
+</form>
+{% endblock %}
http://git-wip-us.apache.org/repos/asf/allura/blob/454565e6/Allura/allura/templates/site_admin_site_notifications_list.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/site_admin_site_notifications_list.html b/Allura/allura/templates/site_admin_site_notifications_list.html
index 7f88e54..f400a96 100644
--- a/Allura/allura/templates/site_admin_site_notifications_list.html
+++ b/Allura/allura/templates/site_admin_site_notifications_list.html
@@ -22,7 +22,7 @@
{% extends 'allura:templates/site_admin.html' %}
{% block content %}
<div class="grid-23"><a href="/nf/admin">Back to Site Admin Home</a></div>
- <div class="grid-23"><a href="">Create a new notification</a></div>
+ <div class="grid-23"><a href="new">Create a new notification</a></div>
{{c.page_size.display(limit=limit, page=page_url, count=count)}}
<table id="site_notifications">
<thead>
@@ -45,8 +45,8 @@
<td><small class="tooltip" title="{{ note.page_regex }}">{{ note.page_regex|truncate(20) if note.page_regex}}</small></td>
<td><small>{{ note.page_tool_type if note.page_tool_type}}</small></td>
<td>
- <a href="">Edit</a><br>
- <a href="">Delete</a>
+ <a href="{{ note._id }}/edit">Edit</a><br>
+ <a href="{{ note._id }}/delete">Delete</a>
</td>
</tr>
{% endfor %}
http://git-wip-us.apache.org/repos/asf/allura/blob/454565e6/Allura/allura/templates/site_admin_site_notifications_new.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/site_admin_site_notifications_new.html b/Allura/allura/templates/site_admin_site_notifications_new.html
new file mode 100644
index 0000000..8123d97
--- /dev/null
+++ b/Allura/allura/templates/site_admin_site_notifications_new.html
@@ -0,0 +1,118 @@
+{#-
+ 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.
+-#}
+{% set page="task_manager" %}
+{% set sidebar_rel = '../' %}
+{% extends 'allura:templates/site_admin.html' %}
+
+{% block extra_css %}
+<style>
+ form {
+ margin: 1em;
+ }
+ form > div {
+ margin-bottom: 1em;
+ }
+ form > div > *{
+ display: inline-block;
+ vertical-align: top;
+ }
+ form > div input,
+ form > div textarea,
+ form > div select,
+ form > .input {
+ display: block;
+ width: 300px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ }
+ form > div label {
+ width: 100px;
+ }
+ .error {
+ width: 300px;
+ background: none;
+ border: none;
+ color: #f00;
+ margin: 0;
+ padding: 0 0 0 .8em;
+ }
+</style>
+{% endblock %}
+
+{% macro error(field) %}
+ {% if form_errors.get(field) %}
+ <span class="error">{{form_errors.get(field)}}</span>
+ {% endif %}
+{% endmacro %}
+
+{% block content %}
+<h2>New Site Notification</h2>
+<form method="POST" action="create" id="newnote">
+ <div>
+ <label>Active</label>
+ <div class="input">
+ <select name="active">
+ <option value="False">No</option>
+ <option value="True" {%- if form_values.get('active') == 'True' -%}selected{%- endif -%}>Yes</option>
+ </select>
+ </div>
+ {{error('active')}}
+ </div>
+ <div>
+ <label>Impressions</label>
+ <div class="input">
+ <input name="impressions" value="{{form_values.get('impressions', '0')}}" />
+ </div>
+ {{error('impressions')}}
+ </div>
+ <div>
+ <label>Content</label>
+ <div class="input">
+ <textarea name="content" rows="4">{{form_values.get('content', '')}}</textarea>
+ </div>
+ {{error('content')}}
+ </div>
+ <div>
+ <label>User Role</label>
+ <div class="input">
+ <input name="user_role" value="{{form_values.get('user_role', '')}}" />
+ </div>
+ {{error('user_role')}}
+ </div>
+ <div>
+ <label>Page Regex</label>
+ <div class="input">
+ <input name="page_regex" value="{{form_values.get('page_regex', '')}}" />
+ </div>
+ {{error('page_regex')}}
+ </div>
+ <div>
+ <label>Page Type</label>
+ <div class="input">
+ <input name="page_tool_type" value="{{form_values.get('page_tool_type', '')}}" />
+ </div>
+ {{error('page_tool_type')}}
+ </div>
+
+
+ <input type="submit" value="Save"/><br/>
+ {{lib.csrf_token()}}
+</form>
+{% endblock %}
http://git-wip-us.apache.org/repos/asf/allura/blob/454565e6/Allura/allura/tests/functional/test_site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py
index 6b4187f..c8f98cc 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -18,6 +18,7 @@
import json
import datetime as dt
+import bson
from mock import patch, MagicMock
from nose.tools import assert_equal, assert_in, assert_not_in
@@ -206,6 +207,120 @@ class TestSiteAdmin(TestController):
assert row[4].contents[0].contents[0] == 'test3'
assert row[5].contents[0].contents[0] == 'test4'
+ def test_site_notification_new_template(self):
+ r = self.app.get('/nf/admin/site_notifications/new')
+
+ assert r
+ assert 'New Site Notification' in r
+ assert 'Active' in r
+ assert 'Impressions' in r
+ assert 'Content' in r
+ assert 'User Role' in r
+ assert 'Page Regex' in r
+ assert 'Page Type' in r
+
+ def test_site_notification_create(self):
+ count = M.notification.SiteNotification.query.find().count()
+ active = 'True'
+ impressions = '7'
+ content = 'test1'
+ user_role = 'test2'
+ page_regex = 'test3'
+ page_tool_type = 'test4'
+ r = self.app.post('/nf/admin/site_notifications/create', params=dict(
+ active=active,
+ impressions=impressions,
+ content=content,
+ user_role=user_role,
+ page_regex=page_regex,
+ page_tool_type=page_tool_type))
+ note = M.notification.SiteNotification.query.find().sort('_id', -1).next()
+
+ assert '/nf/admin/site_notifications' in r.location
+
+ assert M.notification.SiteNotification.query.find().count() == count + 1
+
+ assert note.active == bool('True')
+ assert note.impressions == int(impressions)
+ assert note.content == content
+ assert note.user_role == user_role
+ assert note.page_regex == page_regex
+ assert note.page_tool_type == page_tool_type
+
+ def test_site_notification_edit_template(self):
+ note = M.notification.SiteNotification(active=True,
+ impressions=0,
+ content='test1',
+ user_role='test2',
+ page_regex='test3',
+ page_tool_type='test4')
+ ThreadLocalORMSession().flush_all()
+ r = self.app.get('/nf/admin/site_notifications/{}/edit'.format(note._id))
+
+ assert r
+
+ assert (u'selected', u'selected') in r.html.find('form').findAll('option')[1].attrs
+ assert r.form['impressions'].value == '0'
+ assert r.form['content'].value == 'test1'
+ assert r.form['user_role'].value == 'test2'
+ assert r.form['page_regex'].value == 'test3'
+ assert r.form['page_tool_type'].value == 'test4'
+
+ assert 'Edit Site Notification' in r
+ assert 'Active' in r
+ assert 'Impressions' in r
+ assert 'Content' in r
+ assert 'User Role' in r
+ assert 'Page Regex' in r
+ assert 'Page Type' in r
+
+ def test_site_notification_update(self):
+ active = 'True'
+ impressions = '7'
+ content = 'test1'
+ user_role = 'test2'
+ page_regex = 'test3'
+ page_tool_type = 'test4'
+
+ note = M.notification.SiteNotification(active=False,
+ impressions=0,
+ content='test')
+ ThreadLocalORMSession().flush_all()
+
+ count = M.notification.SiteNotification.query.find().count()
+
+ r = self.app.post('/nf/admin/site_notifications/{}/update'.format(note._id), params=dict(
+ active=active,
+ impressions=impressions,
+ content=content,
+ user_role=user_role,
+ page_regex=page_regex,
+ page_tool_type=page_tool_type))
+ ThreadLocalORMSession().flush_all()
+
+ note = M.notification.SiteNotification.query.find().sort('_id', -1).next()
+
+ assert '/nf/admin/site_notifications' in r.location
+ assert M.notification.SiteNotification.query.find().count() == count
+ assert note.active == bool('True')
+ assert note.impressions == int(impressions)
+ assert note.content == content
+ assert note.user_role == user_role
+ assert note.page_regex == page_regex
+ assert note.page_tool_type == page_tool_type
+
+ def test_site_notification_delete(self):
+ note = M.notification.SiteNotification(active=False,
+ impressions=0,
+ content='test')
+ ThreadLocalORMSession().flush_all()
+
+ count = M.notification.SiteNotification.query.find().count()
+
+ self.app.get('/nf/admin/site_notifications/{}/delete'.format(note._id))
+ assert M.notification.SiteNotification.query.find().count() == count -1
+ assert M.notification.SiteNotification.query.get(_id=bson.ObjectId(note._id)) is None
+
class TestProjectsSearch(TestController):