jenkins-bot has submitted this change and it was merged.

Change subject: Add campaigns to user landing page and add middleware to check 
for campaign
......................................................................


Add campaigns to user landing page and add middleware to check for campaign

Bug: T92620
Change-Id: I4b36a9ab61eb40b5e4ae86305fb08db65cf26f3e
---
M data/i18n/en.json
M data/i18n/qqq.json
M data/templates/admin/base.html
M data/templates/base.html
A data/templates/campaign.html
M data/templates/index.html
M data/templates/nav_user.html
M data/templates/proposals/edit.html
M data/templates/proposals/queue.html
M data/templates/proposals/search.html
M data/templates/proposals/view.html
M data/templates/proposals/view_review_edit.html
M data/templates/reports/report.html
M data/templates/reports/wikitext.html
M data/templates/user/base.html
M src/App.php
M src/Controllers/Admin/Campaign.php
M src/Controllers/Admin/Campaigns.php
M src/Controllers/Admin/User.php
M src/Controllers/Admin/Users.php
A src/Controllers/Campaigns.php
A src/Controllers/Index.php
M src/Controllers/Login.php
M src/Controllers/Proposals/Edit.php
M src/Controllers/Proposals/Queue.php
M src/Controllers/Proposals/Review.php
M src/Controllers/Proposals/Search.php
M src/Controllers/Proposals/View.php
M src/Controllers/Reports/AbstractReport.php
M src/Controllers/Reports/Aggregated.php
M src/Controllers/Reports/Campaigns.php
M src/Controllers/Reports/Wikitext.php
M src/Controllers/User/ChangePassword.php
M src/Dao/Campaigns.php
34 files changed, 415 insertions(+), 104 deletions(-)

Approvals:
  BryanDavis: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/data/i18n/en.json b/data/i18n/en.json
index 9221e45..820c916 100644
--- a/data/i18n/en.json
+++ b/data/i18n/en.json
@@ -22,9 +22,9 @@
        "nav-admin": "Admin",
        "nav-users": "Manage users",
        "nav-account": "My Account",
-       "nav-campaigns": "Manage campaigns",
        "nav-campaigns-reviewers": "Report by reviewers",
        "nav-campaigns-reviewers-proposals": "Proposals",
+       "nav-campaigns": "Campaigns",
 
        "new-account-subject": "New grants review account",
        "new-account-email": "A new grants review account has been created for 
you.\n\nYour login info is:\n\nusername: $1\npassword: $2\n\nYou may login at: 
$3\n\nYou may change your password at: $4\n\nSincerely,\nGrants review 
administrators",
@@ -132,6 +132,10 @@
        "admin-proposal-theme": "Theme",
        "admin-proposal-amount": "Amount",
 
+       "campaigns-welcome": "Welcome reviewer! Pick a campaign to start 
reviewing.",
+       "campaigns-active": "Active campaigns",
+       "campaigns-past": "Past campaigns",
+
        "page-of-pages": "Page $1 of $2",
        "no-results": "No results found",
 
diff --git a/data/i18n/qqq.json b/data/i18n/qqq.json
index 482605b..0ba6cd4 100644
--- a/data/i18n/qqq.json
+++ b/data/i18n/qqq.json
@@ -65,6 +65,10 @@
        "admin-campaign-wikitext": "Label for a wikitext template textarea",
        "admin-campaign-wikitext-placeholder": "Placehodler for wikitext 
template textarea placeholder",
 
+       "campaigns-welcome": "Welcome message for reviewer landing page",
+       "campaigns-active": "Active campaigns header",
+       "campaigns-past": "Past campaigns header",
+
        "change-password": "Navigation menu item, links to password change 
page.\n{{Identical|Change password}}",
        "credits": "Credits page heading",
        "credits-page-license": "Credits page content",
diff --git a/data/templates/admin/base.html b/data/templates/admin/base.html
index a3e7ee3..375c888 100644
--- a/data/templates/admin/base.html
+++ b/data/templates/admin/base.html
@@ -1,2 +1,36 @@
 {% extends "base.html" %}
 {% block title %}{% block subtitle %}{% endblock subtitle %} - {{ parent() 
}}{% endblock title %}
+{% block navbar %}
+<ul class="nav navbar-nav">
+
+<li class="dropdown">
+  <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ 
'nav-campaigns'|message }} <b class="caret"></b></a>
+  <ul class="dropdown-menu">
+    {% for c in listcampaigns %}
+      <li><a href="{{ urlFor( 'proposals_queue', { 'campaign':c.id } ) }}">{{ 
c.name }}</a></li>
+    {% endfor %}
+  </ul>
+</li>
+
+{% if isadmin|default(false) %}
+<li class="dropdown">
+  <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ 
'nav-admin'|message }} <b class="caret"></b></a>
+  <ul class="dropdown-menu">
+    <li><a href="{{ urlFor( 'admin_users' ) }}">{{ 'nav-users'|message 
}}</a></li>
+    <li><a href="{{ urlFor( 'admin_user', { 'id':'new' } ) }}">{{ 
'admin-users-add'|message }}</a></li>
+    <li><a href="{{ urlFor( 'admin_campaigns' ) }}">{{ 
'admin-campaign-manage'|message }}</a></li>
+    <li><a href="{{ urlFor( 'admin_campaign', { 'id':'new' } ) }}">{{ 
'admin-campaign-add'|message }}</a></li>
+  </ul>
+</li>
+{% endif %}
+
+<li class="dropdown">
+  <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ 
'nav-account'|message }} <b class="caret"></b></a>
+  <ul class="dropdown-menu">
+    <li><a href="{{ urlFor( 'user_changepassword' ) }}">{{ 
'change-password'|message }}</a></li>
+    <li><a href="{{ urlFor( 'logout' ) }}">{{ 'logout'|message }}</a></li>
+  </ul>
+</li>
+
+</ul>
+{% endblock navbar %}
\ No newline at end of file
diff --git a/data/templates/base.html b/data/templates/base.html
index f0d6c3e..510a062 100644
--- a/data/templates/base.html
+++ b/data/templates/base.html
@@ -25,14 +25,14 @@
             <span class="icon-bar"></span>
             <span class="icon-bar"></span>
           </button>
-          <a class="navbar-brand" href="{{ urlFor( 'home') }}" title="{{ 
'header-title'|message }}"><img src="{{ siteUrl( 'images/glasses.png' ) }}" 
width="46" height="36" alt="{{ 'logo-alt'|message }}"></a>
+          <a class="navbar-brand" href="{{ urlFor( 'campaigns') }}" title="{{ 
'header-title'|message }}"><img src="{{ siteUrl( 'images/glasses.png' ) }}" 
width="46" height="36" alt="{{ 'logo-alt'|message }}"></a>
         </div>
         <div class="navbar-collapse collapse">
-          <ul class="nav navbar-nav">
             {% block navbar %}
             {% if user|default(false) %}
             {% include 'nav_user.html' %}
             {% else %}
+          <ul class="nav navbar-nav">
             {% block login_form %}
             <form class="navbar-form navbar-right" action="{{ urlFor( 
'login_post' ) }}" method="post" role="form">
                 <input type="hidden" name="{{ csrf_param }}" value="{{ 
csrf_token }}" />
@@ -47,9 +47,9 @@
                 <input type="submit" class="btn btn-default" value="{{ 
'login'|message }}" />
             </form>
             {% endblock login_form %}
+          </ul>
             {% endif %}
             {% endblock navbar %}
-          </ul>
           <div class="navbar-right navbar-text form-inline">
             {% if i18nCtx.getAvailableLanguages|length > 1 %}
             <span class="langlabel">{{ 'nav-language'|message }}</span>
diff --git a/data/templates/campaign.html b/data/templates/campaign.html
new file mode 100644
index 0000000..e6acefe
--- /dev/null
+++ b/data/templates/campaign.html
@@ -0,0 +1,41 @@
+{% extends "base.html" %}
+{% block navbar %}{% endblock navbar %}
+
+{% block content %}
+{% spaceless %}
+<div class="row">
+  <div class="col-md-10 col-md-offset-1">
+    <h2>{{ 'campaigns-welcome'|message }}</h2>
+  </div>
+</div>
+{% if user|default(false) %}
+
+<div class="row">
+  <div class="col-md-10 col-md-offset-1">
+  <h3>{{ 'campaigns-active'|message }}</h3>
+  </div>
+</div>
+  {% for campaign in campaigns if campaign.status == 1 %}
+    <div class="row">
+        <div class="col-md-10 col-md-offset-1">
+          <a href ="{{ urlFor( 'proposals_home', { 'campaign':campaign.id } ) 
}}" >{{ campaign.name }}</a>
+        </div>
+    </div>
+  {% endfor %}
+<div class="row">
+  <div class="col-md-10 col-md-offset-1">
+  <h3>{{ 'campaigns-past'|message }}</h3>
+  </div>
+</div>
+  {% for campaign in campaigns if campaign.status == 0 %}
+    <div class="row">
+        <div class="col-md-10 col-md-offset-1">
+          <a href ="{{ urlFor( 'proposals_home', { 'campaign':campaign.id } ) 
}}" >{{ campaign.name }}</a>
+        </div>
+    </div>
+  {% endfor %}
+
+{% endif %}
+
+{% endspaceless %}
+{% endblock content %}
\ No newline at end of file
diff --git a/data/templates/index.html b/data/templates/index.html
index 27cbcaf..cbd9f5d 100644
--- a/data/templates/index.html
+++ b/data/templates/index.html
@@ -8,5 +8,6 @@
     {{ 'index-page'|message|raw|wikitext }}
   </div>
 </div>
+
 {% endspaceless %}
 {% endblock content %}
diff --git a/data/templates/nav_user.html b/data/templates/nav_user.html
index da06394..0096223 100644
--- a/data/templates/nav_user.html
+++ b/data/templates/nav_user.html
@@ -1,13 +1,14 @@
+<ul class="nav navbar-nav">
 {% if isreviewer|default(false) or isadmin|default(false) %}
 <li class="dropdown">
   <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ 
'nav-proposals'|message }} <b class="caret"></b></a>
   <ul class="dropdown-menu">
     {% if isreviewer|default(false) %}
-    <li><a href="{{ urlFor( 'proposals_queue' ) }}">{{ 
'nav-proposals-queue'|message }}</a></li>
+    <li><a href="{{ urlFor( 'proposals_queue', { 'campaign':campaign } ) 
}}">{{ 'nav-proposals-queue'|message }}</a></li>
     {% endif %}
-    <li><a href="{{ urlFor( 'proposals_search' ) }}">{{ 
'nav-proposals-search'|message }}</a></li>
+    <li><a href="{{ urlFor( 'proposals_search', { 'campaign':campaign } ) 
}}">{{ 'nav-proposals-search'|message }}</a></li>
     {% if isadmin|default(false) %}
-    <li><a href="{{ urlFor( 'proposals_edit', { 'id': 'new' } ) }}">{{ 
'nav-proposals-add'|message }}</a></li>
+    <li><a href="{{ urlFor( 'proposals_edit', { 'id': 'new', 
'campaign':campaign } ) }}">{{ 'nav-proposals-add'|message }}</a></li>
     {% endif %}
   </ul>
 </li>
@@ -17,9 +18,9 @@
 <li class="dropdown">
   <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ 
'nav-reports'|message }} <b class="caret"></b></a>
   <ul class="dropdown-menu">
-    <li><a href="{{ urlFor( 'reports_aggregated' ) }}">{{ 
'nav-reports-aggregated'|message }}</a></li>
-    <li><a href="{{ urlFor( 'reports_campaigns' ) }}">{{ 
'nav-reports-campaigns'|message }}</a></li>
-    <li><a href="{{ urlFor( 'reports_wikitext' ) }}">{{ 
'nav-reports-wikitext'|message }}</a></li>
+    <li><a href="{{ urlFor( 'reports_aggregated', { 'campaign':campaign } ) 
}}">{{ 'nav-reports-aggregated'|message }}</a></li>
+    <li><a href="{{ urlFor( 'reports_campaigns', { 'campaign':campaign } ) 
}}">{{ 'nav-reports-campaigns'|message }}</a></li>
+    <li><a href="{{ urlFor( 'reports_wikitext', { 'campaign':campaign } ) 
}}">{{ 'nav-reports-wikitext'|message }}</a></li>
   </ul>
 </li>
 {% endif %}
@@ -45,3 +46,5 @@
   </ul>
 </li>
 
+</ul>
+
diff --git a/data/templates/proposals/edit.html 
b/data/templates/proposals/edit.html
index a771dcd..2377e6f 100644
--- a/data/templates/proposals/edit.html
+++ b/data/templates/proposals/edit.html
@@ -6,13 +6,14 @@
 {% block content %}
 {% spaceless %}
 <ol class="breadcrumb">
-  <li><a href="{{ urlFor( 'proposals_home' ) }}">{{ 'nav-proposals'|message 
}}</a></li>
+  <li><a href="{{ urlFor( 'campaigns' ) }}">{{ 'nav-campaigns'|message 
}}</a></li>
+  <li><a href="{{ urlFor( 'proposals_home', { 'campaign':campaign } ) }}">{{ 
'nav-proposals'|message }}</a></li>
   {% if id != 'new' %}
-  <li><a href="{{ urlFor( 'proposals_view', { 'id': id } ) }}">{{ form.get( 
'title' )|default( id ) }}</a></li>
+  <li><a href="{{ urlFor( 'proposals_view', { 'id': id, 'campaign':campaign } 
) }}">{{ form.get( 'title' )|default( id ) }}</a></li>
   {% else %}
   <li>{{ id }}</li>
   {% endif %}
-  <li><a href="{{ urlFor( 'proposals_edit', { 'id': id } ) }}">{{ 
'nav-proposals-edit'|message }}</a></li>
+  <li><a href="{{ urlFor( 'proposals_edit', { 'id': id, 'campaign':campaign } 
) }}">{{ 'nav-proposals-edit'|message }}</a></li>
 </ol>
 
 {% if form.hasErrors %}
@@ -22,7 +23,7 @@
 </div>
 {% endif %}
 
-<form class="form-horizontal" method="post" action="{{ urlFor( 
'proposals_edit_post', { 'id': id  } ) }}">
+<form class="form-horizontal" method="post" action="{{ urlFor( 
'proposals_edit_post', { 'id': id, 'campaign':campaign  } ) }}">
   <input type="hidden" name="{{ csrf_param }}" value="{{ csrf_token }}" />
   <input type="hidden" name="id" value="{{ id }}" />
   {{ forms.text( ctx, 'proposals-edit-title', 'title', { 'required':true } ) }}
diff --git a/data/templates/proposals/queue.html 
b/data/templates/proposals/queue.html
index 86780d5..1cba2f4 100644
--- a/data/templates/proposals/queue.html
+++ b/data/templates/proposals/queue.html
@@ -11,14 +11,15 @@
 {% else %}
   {% set nextO = 'asc' %}
 {% endif %}
-<th><a class="sortable {{ sorted ? "sorted-#{o}" : 'unsorted' }} {{ 
class|default( '' ) }}" href="{{ urlFor( ctx.route ) }}?{{ qsMerge( { 
's':column, 'o':nextO } ) }}">{{ label|message }}</a></th>
+<th><a class="sortable {{ sorted ? "sorted-#{o}" : 'unsorted' }} {{ 
class|default( '' ) }}" href="{{ urlFor( ctx.route, { 'campaign':ctx.campaign } 
) }}?{{ qsMerge( { 's':column, 'o':nextO } ) }}">{{ label|message }}</a></th>
 {% endmacro %}
 
 {% block subtitle %}{{ 'nav-proposals-queue'|message }}{% endblock %}
 {% block content %}
 {% spaceless %}
 <ol class="breadcrumb">
-  <li><a href="{{ urlFor( 'proposals_home' ) }}">{{ 'nav-proposals'|message 
}}</a></li>
+  <li><a href="{{ urlFor( 'campaigns' ) }}">{{ 'nav-campaigns'|message 
}}</a></li>
+  <li><a href="{{ urlFor( 'proposals_home', { 'campaign':campaign } ) }}">{{ 
'nav-proposals'|message }}</a></li>
   <li>{{ 'nav-proposals-queue'|message }}</li>
 </ol>
 
@@ -26,7 +27,7 @@
     {{ 'proposals-queue-intro'|message|raw|wikitext }}
 </section>
 
-<form class="form-inline" method="get" action="{{ urlFor( route ) }}" 
role="form">
+<form class="form-inline" method="get" action="{{ urlFor( route, { 
'campaign':campaign } ) }}" role="form">
   <input type="hidden" name="p" value="0">
   <input type="hidden" name="o" value="{{ o }}">
   <input type="hidden" name="s" value="{{ s }}">
@@ -66,7 +67,7 @@
   </tr>
   {% for row in records %}
   <tr>
-    <td><a href="{{ urlFor( 'proposals_view', { 'id': row.id } ) }}">{{ 
row.title }}</a></td>
+    <td><a href="{{ urlFor( 'proposals_view', { 'id': row.id, 
'campaign':campaign } ) }}">{{ row.title }}</a></td>
     <td>{{ row.theme }}</td>
     <td class="text-right nowrap">
         {{ row.amount|number_format }}
diff --git a/data/templates/proposals/search.html 
b/data/templates/proposals/search.html
index 43c546d..3369f43 100644
--- a/data/templates/proposals/search.html
+++ b/data/templates/proposals/search.html
@@ -10,26 +10,27 @@
 {% else %}
   {% set nextO = 'asc' %}
 {% endif %}
-<th><a class="sortable {{ sorted ? "sorted-#{o}" : 'unsorted' }} {{ 
class|default( '' ) }}" href="{{ urlFor( ctx.route ) }}?{{ qsMerge( { 
's':column, 'o':nextO } ) }}">{{ label|message }}</a></th>
+<th><a class="sortable {{ sorted ? "sorted-#{o}" : 'unsorted' }} {{ 
class|default( '' ) }}" href="{{ urlFor( ctx.route, { 'campaign':campaign } ) 
}}?{{ qsMerge( { 's':column, 'o':nextO } ) }}">{{ label|message }}</a></th>
 {% endmacro %}
 
 {% block subtitle %}{{ 'nav-proposals-search'|message }}{% endblock %}
 {% block content %}
 {% spaceless %}
 <ol class="breadcrumb">
-  <li><a href="{{ urlFor( 'proposals_home' ) }}">{{ 'nav-proposals'|message 
}}</a></li>
-  <li><a href="{{ urlFor( route ) }}">{{ 'nav-proposals-search'|message 
}}</a></li>
+  <li><a href="{{ urlFor( 'campaigns' ) }}">{{ 'nav-campaigns'|message 
}}</a></li>
+  <li><a href="{{ urlFor( 'proposals_home', { 'campaign':campaign } ) }}">{{ 
'nav-proposals'|message }}</a></li>
+  <li><a href="{{ urlFor( route, { 'campaign':campaign } ) }}">{{ 
'nav-proposals-search'|message }}</a></li>
 </ol>
 
-<form class="form-inline" method="get" action="{{ urlFor( route ) }}" 
role="form">
+<form class="form-inline" method="get" action="{{ urlFor( route, { 
'campaign':campaign } ) }}" role="form">
   <input type="hidden" name="p" value="0">
 
   <div class="form-group">
-    <label class="sr-only" for="campaign">{{ 
'proposals-search-campaigns-empty'|message }}</label>
-    <select id="campaign" name="campaign" class="form-control">
+    <label class="sr-only" for="campaign-select">{{ 
'proposals-search-campaigns-empty'|message }}</label>
+    <select id="campaign-select" name="campaign-select" class="form-control">
       <option value="">{{ 'proposals-search-campaigns-empty'|message 
}}</option>
       {% for id, name in campaigns %}
-        <option value="{{ id }}" {{ id == campaign ? 'selected="selected"' 
}}>{{ name }}</option>
+        <option value="{{ id }}" {{ id == campaign-select ? 
'selected="selected"' }}>{{ name }}</option>
       {% endfor %}
     </select>
   </div>
@@ -84,7 +85,7 @@
   {% for row in records %}
   <tr>
     <td class="text-right">{{ row.id }}</td>
-    <td><a href="{{ urlFor( 'proposals_view', { 'id':row.id } ) }}">{{ 
row.title }}</a></td>
+    <td><a href="{{ urlFor( 'proposals_view', { 'id':row.id, 
'campaign':campaign } ) }}">{{ row.title }}</a></td>
     <td>{{ row.theme }}</td>
     <td class="text-right">{{ row.amount|number_format }}</td>
     <td class="text-right">{{ row.review_count|number_format }}</td>
@@ -102,7 +103,7 @@
   <div class="col-md-9">
     <ul class="pagination">
       {% if p > 0 %}
-      <li><a href="{{ urlFor( route ) }}?{{ qsMerge( { 'p':(p - 1) } ) }}" 
id="prev">&laquo;</a></li>
+      <li><a href="{{ urlFor( route, { 'campaign':campaign } ) }}?{{ qsMerge( 
{ 'p':(p - 1) } ) }}" id="prev">&laquo;</a></li>
       {% else %}
       <li class="disabled"><span>&laquo;</span></li>
       {% endif %}
diff --git a/data/templates/proposals/view.html 
b/data/templates/proposals/view.html
index 306c46f..4b5af22 100644
--- a/data/templates/proposals/view.html
+++ b/data/templates/proposals/view.html
@@ -4,8 +4,9 @@
 {% block content %}
 {% spaceless %}
 <ol class="breadcrumb">
-  <li><a href="{{ urlFor( 'proposals_home' ) }}">{{ 'nav-proposals'|message 
}}</a></li>
-  <li><a href="{{ urlFor( 'proposals_view', { 'id': proposal.id } ) }}">{{ 
proposal.title }}</a></li>
+  <li><a href="{{ urlFor( 'campaigns' ) }}">{{ 'nav-campaigns'|message 
}}</a></li>
+  <li><a href="{{ urlFor( 'proposals_home', { 'campaign':campaign } ) }}">{{ 
'nav-proposals'|message }}</a></li>
+  <li><a href="{{ urlFor( 'proposals_view', { 'id': proposal.id, 
'campaign':campaign } ) }}">{{ proposal.title }}</a></li>
 </ol>
 
 <article id="proposal" class="panel-group">
@@ -48,7 +49,7 @@
       {% endif %}
       {% if isadmin|default(false) %}
       <div class="text-right">
-        <a class="btn btn-sm" href="{{ urlFor( 'proposals_edit', { 'id': 
proposal.id } ) }}"><span class="glyphicon glyphicon-edit"></span> {{ 
'proposals-view-edit'|message }}</a>
+        <a class="btn btn-sm" href="{{ urlFor( 'proposals_edit', { 'id': 
proposal.id, 'campaign':campaign } ) }}"><span class="glyphicon 
glyphicon-edit"></span> {{ 'proposals-view-edit'|message }}</a>
       </div>
       {% endif %}
     </div>
@@ -64,8 +65,8 @@
 {% endif %}
 
 <ol class="breadcrumb">
-  <li><a href="{{ urlFor( 'proposals_home' ) }}">{{ 'nav-proposals'|message 
}}</a></li>
-  <li><a href="{{ urlFor( 'proposals_view', { 'id': proposal.id } ) }}">{{ 
proposal.title }}</a></li>
+  <li><a href="{{ urlFor( 'proposals_home', { 'campaign':campaign } ) }}">{{ 
'nav-proposals'|message }}</a></li>
+  <li><a href="{{ urlFor( 'proposals_view', { 'id': proposal.id, 
'campaign':campaign } ) }}">{{ proposal.title }}</a></li>
 </ol>
 {% endspaceless %}
 {% endblock content %}
diff --git a/data/templates/proposals/view_review_edit.html 
b/data/templates/proposals/view_review_edit.html
index 6272792..45df43a 100644
--- a/data/templates/proposals/view_review_edit.html
+++ b/data/templates/proposals/view_review_edit.html
@@ -28,7 +28,7 @@
     </div>
     <div id="review-body" class="panel-body panel-collapse collapse {% if 
myreview is empty %}in{% endif %}">
       {{ 'review-instructions'|message|raw|wikitext }}
-      <form method="post" action="{{ urlFor( 'proposals_review_post', { 'id': 
proposal.id } ) }}">
+      <form method="post" action="{{ urlFor( 'proposals_review_post', { 'id': 
proposal.id, 'campaign':campaign } ) }}">
         <input type="hidden" name="{{ csrf_param }}" value="{{ csrf_token }}" 
/>
         <input type="hidden" name="proposal" value="{{ proposal.id }}" />
 
diff --git a/data/templates/reports/report.html 
b/data/templates/reports/report.html
index eab9fcf..40512c1 100644
--- a/data/templates/reports/report.html
+++ b/data/templates/reports/report.html
@@ -29,10 +29,10 @@
 {% else %}
   {% set class = '' %}
 {% endif %}
-<th><a class="sortable {{ sorted ? "sorted-#{o}" : 'unsorted' }} {{ class }}" 
href="{{ urlFor( ctx.route ) }}?{{ qsMerge( { 's':column, 'o':nextO } ) }}">{{ 
label }}</a></th>
+<th><a class="sortable {{ sorted ? "sorted-#{o}" : 'unsorted' }} {{ class }}" 
href="{{ urlFor( ctx.route, { 'campaign':campaign } ) }}?{{ qsMerge( { 
's':column, 'o':nextO } ) }}">{{ label }}</a></th>
 {% endmacro %}
 
-{% macro format( row, spec ) %}
+{% macro format( row, spec, ctx ) %}
 {% set val = row[spec.column] %}
 {% if spec.format == 'number' %}
   <td class="text-right">{{ row[spec.column]|number_format( spec.precision ) 
}}</td>
@@ -42,7 +42,7 @@
     {{ 'currency-usd'|message }}
   </td>
 {% elseif spec.format == 'proposal' %}
-  <td><a href="{{ urlFor( 'proposals_view', { 'id':row[spec.column] } ) }}">{{ 
row[spec.text] }}</a></td>
+  <td><a href="{{ urlFor( 'proposals_view', { 'id':row[spec.column], 
'campaign':ctx.campaign } ) }}">{{ row[spec.text] }}</a></td>
 {% elseif spec.format == 'message' %}
   {% set vals = [] %}
   {% for key in spec.columns %}
@@ -50,7 +50,7 @@
   {% endfor %}
   <td class="text-center">{{ spec.message|message( vals ) }}</td>
 {% elseif spec.format == 'campaign' %}
-  <td><a href="{{ urlFor( 'proposals_search' ) }}?campaign={{ row[spec.column] 
}}">
+  <td><a href="{{ urlFor( 'proposals_search', { 'campaign':ctx.campaign } ) 
}}?campaign={{ row[spec.column] }}">
     {{ row[spec.text]}}
   </a></td>
 {% else %}
@@ -64,8 +64,9 @@
 {% block content %}
 {% spaceless %}
 <ol class="breadcrumb">
+  <li><a href="{{ urlFor( 'campaigns' ) }}">{{ 'nav-campaigns'|message 
}}</a></li>
   <li>{{ 'nav-reports'|message }}</li>
-  <li><a href="{{ urlFor( route ) }}">{{ ( 'nav-reports-' ~ suffix )|message 
}}</a></li>
+  <li><a href="{{ urlFor( route, { 'campaign':campaign } ) }}">{{ ( 
'nav-reports-' ~ suffix )|message }}</a></li>
 </ol>
 
 <table class="table table-striped table-hover table-condensed 
table-responsive">
@@ -85,7 +86,7 @@
     {% for row in report.rows %}
     <tr>
       {% for col in columns %}
-      {{ _self.format( row, col ) }}
+      {{ _self.format( row, col, ctx ) }}
       {% endfor %}
     </tr>
     {% else %}
@@ -102,17 +103,17 @@
   <div class="col-md-9">
     <ul class="pagination">
       {% if p > 0 %}
-      <li><a href="{{ urlFor( route ) }}?{{ qsMerge( { 'p':(p - 1) } ) }}" 
id="prev">&laquo;</a></li>
+      <li><a href="{{ urlFor( route, { 'campaign':campaign } ) }}?{{ qsMerge( 
{ 'p':(p - 1) } ) }}" id="prev">&laquo;</a></li>
       {% else %}
       <li class="disabled"><span>&laquo;</span></li>
       {% endif %}
       {% if left > 0 %}<li class="disabled"><span>&hellip;</span></li>{% endif 
%}
       {% for i in left .. right %}
-      <li class="{{ i == p ? 'active' }}"><a href="{{ urlFor( route ) }}?{{ 
qsMerge( { 'p':i } ) }}" id="prev">{{ i + 1 }}</a></li>
+      <li class="{{ i == p ? 'active' }}"><a href="{{ urlFor( route, { 
'campaign':campaign } ) }}?{{ qsMerge( { 'p':i } ) }}" id="prev">{{ i + 1 
}}</a></li>
       {% endfor %}
       {% if right < pages - 1 %}<li 
class="disabled"><span>&hellip;</span></li>{% endif %}
       {% if p + 1 < pages %}
-      <li><a href="{{ urlFor( route ) }}?{{ qsMerge( { 'p':(p + 1) } ) }}" 
>&raquo;</a></li>
+      <li><a href="{{ urlFor( route, { 'campaign':campaign } ) }}?{{ qsMerge( 
{ 'p':(p + 1) } ) }}" >&raquo;</a></li>
       {% else %}
       <li class="disabled"><span>&raquo;</span></li>
       {% endif %}
diff --git a/data/templates/reports/wikitext.html 
b/data/templates/reports/wikitext.html
index d100758..9643977 100644
--- a/data/templates/reports/wikitext.html
+++ b/data/templates/reports/wikitext.html
@@ -5,11 +5,12 @@
 {% block content %}
 {% spaceless %}
 <ol class="breadcrumb">
+  <li><a href="{{ urlFor( 'campaigns' ) }}">{{ 'nav-campaigns'|message 
}}</a></li>
   <li>{{ 'nav-reports'|message }}</li>
-  <li><a href="{{ urlFor( 'reports_wikitext' ) }}">{{ 
'nav-reports-wikitext'|message }}</a></li>
+  <li><a href="{{ urlFor( 'reports_wikitext', { 'campaign':campaign } ) }}">{{ 
'nav-reports-wikitext'|message }}</a></li>
 </ol>
 
-<form class="form-inline" method="get" action="{{ urlFor( 'reports_wikitext' ) 
}}" role="form">
+<form class="form-inline" method="get" action="{{ urlFor( 'reports_wikitext', 
{ 'campaign':campaign } ) }}" role="form">
   <div class="form-group">
     <label class="sr-only" for="th">{{ 'proposals-queue-theme'|message 
}}</label>
     <select id="th" name="th" class="form-control">
diff --git a/data/templates/user/base.html b/data/templates/user/base.html
index a3e7ee3..933d40c 100644
--- a/data/templates/user/base.html
+++ b/data/templates/user/base.html
@@ -1,2 +1,37 @@
 {% extends "base.html" %}
 {% block title %}{% block subtitle %}{% endblock subtitle %} - {{ parent() 
}}{% endblock title %}
+
+{% block navbar %}
+<ul class="nav navbar-nav">
+
+<li class="dropdown">
+  <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ 
'nav-campaigns'|message }} <b class="caret"></b></a>
+  <ul class="dropdown-menu">
+    {% for c in listcampaigns %}
+      <li><a href="{{ urlFor( 'proposals_queue', { 'campaign':c.id } ) }}">{{ 
c.name }}</a></li>
+    {% endfor %}
+  </ul>
+</li>
+
+{% if isadmin|default(false) %}
+<li class="dropdown">
+  <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ 
'nav-admin'|message }} <b class="caret"></b></a>
+  <ul class="dropdown-menu">
+    <li><a href="{{ urlFor( 'admin_users' ) }}">{{ 'nav-users'|message 
}}</a></li>
+    <li><a href="{{ urlFor( 'admin_user', { 'id':'new' } ) }}">{{ 
'admin-users-add'|message }}</a></li>
+    <li><a href="{{ urlFor( 'admin_campaigns' ) }}">{{ 
'admin-campaign-manage'|message }}</a></li>
+    <li><a href="{{ urlFor( 'admin_campaign', { 'id':'new' } ) }}">{{ 
'admin-campaign-add'|message }}</a></li>
+  </ul>
+</li>
+{% endif %}
+
+<li class="dropdown">
+  <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ 
'nav-account'|message }} <b class="caret"></b></a>
+  <ul class="dropdown-menu">
+    <li><a href="{{ urlFor( 'user_changepassword' ) }}">{{ 
'change-password'|message }}</a></li>
+    <li><a href="{{ urlFor( 'logout' ) }}">{{ 'logout'|message }}</a></li>
+  </ul>
+</li>
+
+</ul>
+{% endblock navbar %}
\ No newline at end of file
diff --git a/src/App.php b/src/App.php
index 1c3bee1..1bb50c8 100644
--- a/src/App.php
+++ b/src/App.php
@@ -388,6 +388,17 @@
                                        $slim->redirect( $slim->urlFor( 'login' 
) );
                                }
                        },
+
+                       'require-viewcampaign' => function ( $route ) use ( 
$slim ) {
+                               $user = $slim->authManager->getUserId();
+                               $campaign = $route->getParam('campaign');
+                               if ( $slim->campaignsDao->isReviewer( 
$campaign, $user ) === false ) {
+                                       // Redirect to home page
+                                       $slim->flash( 'error', 'You cannot 
access this campaign' );
+                                       $slim->flashKeep();
+                                       $slim->redirect( $slim->urlFor( 
'campaigns' ) );
+                               }
+                       }
                );
 
                // "Root" routes for non-autenticated users
@@ -396,10 +407,23 @@
                        function () use ( $slim, $middleware ) {
                                $slim->get( '', function () use ( $slim ) {
                                        $slim->flashKeep();
-                                       $slim->redirect( $slim->urlFor( 'index' 
) );
+                                       $slim->redirect( $slim->urlFor( 
'campaigns' ) );
                                } )->name( 'home' );
 
-                               App::template( $slim, 'index' );
+                               $slim->get( 'campaigns', 
$middleware['must-revalidate'],
+                                       function () use ( $slim ) {
+                                               $page = new 
Controllers\Campaigns( $slim );
+                                               $page->setDao( 
$slim->campaignsDao );
+                                               $page();
+                                       }
+                               )->name( 'campaigns' );
+
+                               $slim->get( 'index', function () use ( $slim ) {
+                                       $page = new Controllers\Index( $slim );
+                                       $page->setDao( $slim->campaignsDao );
+                                       $page();
+                               } )->name( 'index' );
+
                                App::template( $slim, 'credits' );
                                App::template( $slim, 'privacy' );
 
@@ -451,99 +475,107 @@
 
                                $slim->get( 'changePassword', function () use ( 
$slim ) {
                                        $page = new 
Controllers\User\ChangePassword( $slim );
+                                       $page->setCampaignsDao( 
$slim->campaignsDao );
                                        $page();
                                } )->name( 'user_changepassword' );
 
                                $slim->post( 'changePassword.post', function () 
use ( $slim ) {
                                        $page = new 
Controllers\User\ChangePassword( $slim );
                                        $page->setDao( $slim->usersDao );
+                                       $page->setCampaignsDao( 
$slim->campaignsDao );
                                        $page();
                                } )->name( 'user_changepassword_post' );
                        }
                );
 
                // Routes for proposals
-               $slim->group( '/proposals/',
+               $slim->group( '/campaign/:campaign/proposals/',
                        $middleware['must-revalidate'],
                        $middleware['inject-user'],
                        $middleware['require-user'],
+                       $middleware['require-viewcampaign'],
                        function () use ( $slim, $middleware ) {
-                               $slim->get( '', function () use ( $slim ) {
+                               $slim->get( '', function ( $campaign ) use ( 
$slim ) {
                                        $slim->flashKeep();
-                                       $slim->redirect( $slim->urlFor( 
'proposals_queue' ) );
+                                       $slim->redirect(
+                                               $slim->urlFor( 
'proposals_queue', array( 'campaign' => $campaign ) )
+                                       );
                                } )->name( 'proposals_home' );
 
-                               $slim->get( 'queue', function () use ( $slim ) {
+                               $slim->get( 'queue', function ( $campaign ) use 
( $slim ) {
                                        $page = new 
Controllers\Proposals\Queue( $slim );
                                        $page->setDao( $slim->proposalsDao );
-                                       $page();
+                                       $page( $campaign );
                                } )->name( 'proposals_queue' );
 
-                               $slim->get( 'search', function () use ( $slim ) 
{
+                               $slim->get( 'search', function ( $campaign ) 
use ( $slim ) {
                                        $page = new 
Controllers\Proposals\Search( $slim );
                                        $page->setDao( $slim->proposalsDao );
-                                       $page();
+                                       $page( $campaign );
                                } )->name( 'proposals_search' );
 
-                               $slim->get( ':id/edit', function ( $id ) use ( 
$slim ) {
+                               $slim->get( ':id/edit', function ( $campaign, 
$id ) use ( $slim ) {
                                        $page = new Controllers\Proposals\Edit( 
$slim );
                                        $page->setDao( $slim->proposalsDao );
-                                       $page( $id );
+                                       $page( $campaign, $id );
                                } )->name( 'proposals_edit' );
 
-                               $slim->post( ':id/edit/post', function ( $id ) 
use ( $slim ) {
+                               $slim->post( ':id/edit/post', function ( 
$campaign, $id ) use ( $slim ) {
                                        $page = new Controllers\Proposals\Edit( 
$slim );
                                        $page->setDao( $slim->proposalsDao );
-                                       $page( $id );
+                                       $page( $campaign, $id );
                                } )->name( 'proposals_edit_post' );
 
-                               $slim->post( ':id/review', function ( $id ) use 
( $slim ) {
+                               $slim->post( ':id/review', function ( 
$campaign, $id ) use ( $slim ) {
                                        $page = new 
Controllers\Proposals\Review( $slim );
                                        $page->setDao( $slim->reviewsDao );
                                        $page->setCampaignsDao( 
$slim->campaignsDao );
-                                       $page( $id );
+                                       $page( $campaign, $id );
                                } )->name( 'proposals_review_post' );
 
-                               $slim->get( ':id', function ( $id ) use ( $slim 
) {
+                               $slim->get( ':id', function ( $campaign, $id ) 
use ( $slim ) {
                                        $page = new Controllers\Proposals\View( 
$slim );
                                        $page->setDao( $slim->proposalsDao );
                                        $page->setReviewsDao( $slim->reviewsDao 
);
                                        $page->setCampaignsDao( 
$slim->campaignsDao );
-                                       $page( $id );
+                                       $page( $campaign, $id );
                                } )->name( 'proposals_view' );
                        }
                );
 
                // Routes for reports
-               $slim->group( '/reports/',
+               $slim->group( '/campaign/:campaign/reports/',
                        $middleware['must-revalidate'],
                        $middleware['inject-user'],
                        $middleware['require-user'],
                        $middleware['require-viewreports'],
+                       $middleware['require-viewcampaign'],
                        function () use ( $slim, $middleware ) {
-                               $slim->get( '', function () use ( $slim ) {
+                               $slim->get( '', function ( $campaign ) use ( 
$slim ) {
                                        $slim->flashKeep();
-                                       $slim->redirect( $slim->urlFor( 
'reports_aggregated' ) );
+                                       $slim->redirect( $slim->urlFor( 
'reports_aggregated',
+                                               array( 'campaign' => $campaign )
+                                       ) );
                                } )->name( 'reports_home' );
 
-                               $slim->get( 'aggregated', function () use ( 
$slim ) {
+                               $slim->get( 'aggregated', function ( $campaign 
) use ( $slim ) {
                                        $page = new 
Controllers\Reports\Aggregated( $slim );
                                        $page->setDao( $slim->reportsDao );
                                        $page->setCampaignsDao( 
$slim->campaignsDao );
-                                       $page();
+                                       $page( $campaign );
                                } )->name( 'reports_aggregated' );
 
-                               $slim->get( 'wikitext', function () use ( $slim 
) {
+                               $slim->get( 'wikitext', function ( $campaign ) 
use ( $slim ) {
                                        $page = new 
Controllers\Reports\Wikitext( $slim );
                                        $page->setDao( $slim->reportsDao );
                                        $page->setCampaignsDao( 
$slim->campaignsDao );
-                                       $page();
+                                       $page( $campaign );
                                } )->name( 'reports_wikitext' );
 
-                               $slim->get( 'campaigns', function () use ( 
$slim ) {
+                               $slim->get( 'campaigns', function ( $campaign ) 
use ( $slim ) {
                                        $page = new 
Controllers\Reports\Campaigns( $slim );
                                        $page->setDao( $slim->reportsDao );
-                                       $page();
+                                       $page( $campaign );
                                } )->name( 'reports_campaigns' );
                        }
                );
@@ -557,18 +589,21 @@
                                $slim->get( 'users', function () use ( $slim ) {
                                        $page = new Controllers\Admin\Users( 
$slim );
                                        $page->setDao( $slim->usersDao );
+                                       $page->setCampaignsDao( 
$slim->campaignsDao );
                                        $page();
                                } )->name( 'admin_users' );
 
                                $slim->get( 'user/:id', function ( $id ) use ( 
$slim ) {
                                        $page = new Controllers\Admin\User( 
$slim );
                                        $page->setDao( $slim->usersDao );
+                                       $page->setCampaignsDao( 
$slim->campaignsDao );
                                        $page( $id );
                                } )->name( 'admin_user' );
 
                                $slim->post( 'user.post', function () use ( 
$slim ) {
                                        $page = new Controllers\Admin\User( 
$slim );
                                        $page->setDao( $slim->usersDao );
+                                       $page->setCampaignsDao( 
$slim->campaignsDao );
                                        $page->setMailer( $slim->mailer );
                                        $page();
                                } )->name( 'admin_user_post' );
diff --git a/src/Controllers/Admin/Campaign.php 
b/src/Controllers/Admin/Campaign.php
index 02af1ca..6e6169e 100644
--- a/src/Controllers/Admin/Campaign.php
+++ b/src/Controllers/Admin/Campaign.php
@@ -114,6 +114,7 @@
                $this->view->set( 'campaign', $campaign );
                $this->view->set( 'rev', $reviewers );
                $this->view->set( 'ques', $questions );
+               $this->view->set( 'listcampaigns', 
$this->dao->getUserCampaigns() );
                $this->render( 'admin/campaign.html' );
        }
 
diff --git a/src/Controllers/Admin/Campaigns.php 
b/src/Controllers/Admin/Campaigns.php
index 66583f8..4ccf607 100644
--- a/src/Controllers/Admin/Campaigns.php
+++ b/src/Controllers/Admin/Campaigns.php
@@ -70,7 +70,7 @@
                $this->view->set( 'pages', $pageCount );
                $this->view->set( 'left', $first );
                $this->view->set( 'right', $last );
-
+               $this->view->set( 'listcampaigns', 
$this->dao->getUserCampaigns() );
                $this->render( 'admin/campaigns.html' );
        }
 
diff --git a/src/Controllers/Admin/User.php b/src/Controllers/Admin/User.php
index 6bd7111..37492f3 100644
--- a/src/Controllers/Admin/User.php
+++ b/src/Controllers/Admin/User.php
@@ -34,6 +34,13 @@
  */
 class User extends Controller {
 
+       protected $campaignsDao;
+
+
+       public function setCampaignsDao( $dao ) {
+               $this->campaignsDao = $dao;
+       }
+
        protected function handleGet( $id ) {
                if ( $id === 'new' ) {
                        $user = array(
@@ -53,6 +60,7 @@
 
                $this->view->set( 'id', $id );
                $this->view->set( 'u', $user );
+               $this->view->set( 'listcampaigns', 
$this->campaignsDao->getUserCampaigns() );
                $this->render( 'admin/user.html' );
        }
 
diff --git a/src/Controllers/Admin/Users.php b/src/Controllers/Admin/Users.php
index 48e037c..a853eba 100644
--- a/src/Controllers/Admin/Users.php
+++ b/src/Controllers/Admin/Users.php
@@ -33,6 +33,13 @@
  */
 class Users extends Controller {
 
+       protected $campaignsDao;
+
+
+       public function setCampaignsDao( $dao ) {
+               $this->campaignsDao = $dao;
+       }
+
        protected function handleGet() {
                $this->form->expectString( 'name' );
                $this->form->expectString( 'email' );
@@ -72,6 +79,7 @@
                $this->view->set( 'pages', $pageCount );
                $this->view->set( 'left', $first );
                $this->view->set( 'right', $last );
+               $this->view->set( 'listcampaigns', 
$this->campaignsDao->getUserCampaigns() );
 
                $this->render( 'admin/users.html' );
        }
diff --git a/src/Controllers/Campaigns.php b/src/Controllers/Campaigns.php
new file mode 100644
index 0000000..9b607da
--- /dev/null
+++ b/src/Controllers/Campaigns.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * @section LICENSE
+ * This file is part of Wikimedia Grants Review application.
+ *
+ * Wikimedia Grants Review application is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * Wikimedia Grants Review application is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Wikimedia Grants Review application.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @copyright © 2015 Niharika Kohli, Wikimedia Foundation and contributors.
+ */
+
+namespace Wikimedia\IEGReview\Controllers;
+
+use Wikimedia\IEGReview\Controller;
+
+/**
+ * Landing page after authentication which lists all the campaigns.
+ *
+ * @author Niharika Kohli <[email protected]>
+ * @copyright © 2015 Niharika Kohli, Wikimedia Foundation and contributors.
+ */
+class Campaigns extends Controller {
+
+       protected function handleGet() {
+               $campaigns = $this->dao->getUserCampaigns();
+               $this->view->set( 'campaigns', $campaigns );
+               $this->render( 'campaign.html' );
+       }
+
+       protected function handlePost() {
+               $this->redirect( $this->urlFor( 'login' ) );
+       }
+
+}
diff --git a/src/Controllers/Index.php b/src/Controllers/Index.php
new file mode 100644
index 0000000..2b618da
--- /dev/null
+++ b/src/Controllers/Index.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @section LICENSE
+ * This file is part of Wikimedia Grants Review application.
+ *
+ * Wikimedia Grants Review application is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * Wikimedia Grants Review application is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with Wikimedia Grants Review application.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * @file
+ * @copyright © 2015 Niharika Kohli, Wikimedia Foundation and contributors.
+ */
+
+namespace Wikimedia\IEGReview\Controllers;
+
+use Wikimedia\IEGReview\AuthManager;
+use Wikimedia\IEGReview\Controller;
+
+/**
+ * Routes related to authentication.
+ *
+ * @author Niharika Kohli <[email protected]>
+ * @copyright © 2015 Niharika Kohli, Wikimedia Foundation and contributors.
+ */
+class Index extends Controller {
+
+       protected function handleGet() {
+               $this->render( 'index.html' );
+       }
+
+       protected function handlePost() {
+               $this->redirect( $this->urlFor( 'login' ) );
+       }
+
+}
diff --git a/src/Controllers/Login.php b/src/Controllers/Login.php
index 5a3040f..31396f5 100644
--- a/src/Controllers/Login.php
+++ b/src/Controllers/Login.php
@@ -56,7 +56,7 @@
 
                        if ( $authed ) {
                                $this->flash( 'info', 
$this->i18nContext->message( 'login-success' ) );
-                               $this->redirect( $next ?: $this->urlFor( 'home' 
) );
+                               $this->redirect( $next ?: $this->urlFor( 
'campaigns' ) );
 
                        } else {
                                $this->flash( 'error', 
$this->i18nContext->message( 'login-failed' ) );
diff --git a/src/Controllers/Proposals/Edit.php 
b/src/Controllers/Proposals/Edit.php
index 1ccb6df..3d0dfc5 100644
--- a/src/Controllers/Proposals/Edit.php
+++ b/src/Controllers/Proposals/Edit.php
@@ -79,21 +79,24 @@
                $this->view->setData( 'form', $this->form );
        }
 
-       protected function handleGet( $id ) {
+       protected function handleGet( $campaign, $id ) {
                if ( is_numeric( $id ) ) {
                        $proposal = $this->dao->getProposal( $id );
                } else {
                        $proposal = array();
                }
-               $this->setupForm( $proposal );
+               $this->setupForm( $proposal, $campaign );
                $this->view->setData( 'id', $id );
+               $this->view->set( 'campaign', $campaign );
                $this->render( 'proposals/edit.html' );
        }
 
-       protected function handlePost() {
+       protected function handlePost( $campaign ) {
                $id = $this->request->post( 'id' );
                $this->setupForm( array() );
-               $redir = $this->urlFor( 'proposals_edit', array( 'id' => $id ) 
);
+               $redir = $this->urlFor( 'proposals_edit',
+                       array( 'id' => $id, 'campaign' => $campaign )
+               );
 
                if ( $this->form->validate() ) {
                        $proposal = array(
@@ -104,7 +107,7 @@
                                'theme' => $this->form->get( 'theme' ),
                                'notes' => $this->form->get( 'notes' ),
                                'status' => $this->form->get( 'status' ),
-                               'campaign' => $this->activeCampaign
+                               'campaign' => $campaign
                        );
 
                        if ( is_numeric( $id ) ) {
@@ -118,8 +121,8 @@
 
                        if ( $ok ) {
                                $this->flash( 'info', $this->msg( 
'proposals-edit-save' ) );
-                               $redir = $this->urlFor(
-                                       'proposals_view', array( 'id' => $id )
+                               $redir = $this->urlFor( 'proposals_view',
+                                               array( 'id' => $id, 'campaign' 
=> $campaign )
                                );
                        } else {
                                $this->flash( 'error',
diff --git a/src/Controllers/Proposals/Queue.php 
b/src/Controllers/Proposals/Queue.php
index 8f4cd5a..37062ca 100644
--- a/src/Controllers/Proposals/Queue.php
+++ b/src/Controllers/Proposals/Queue.php
@@ -33,7 +33,7 @@
  */
 class Queue extends Controller {
 
-       protected function handleGet() {
+       protected function handleGet( $campaign ) {
                $this->form->expectString( 'type', array( 'default' => 
'myqueue' ) );
                $this->form->expectString( 'th' );
                $this->form->expectInt( 'items',
@@ -53,6 +53,7 @@
                $this->view->set( 's', $this->form->get( 's' ) );
                $this->view->set( 'o', $this->form->get( 'o' ) );
                $this->view->set( 'found', null );
+               $this->view->set( 'campaign', $campaign );
 
                $params = array(
                        'type' => $this->form->get( 'type' ),
@@ -61,7 +62,7 @@
                        'page' => $this->form->get( 'p' ),
                        'sort' => $this->form->get( 's' ),
                        'order' => $this->form->get( 'o' ),
-                       'campaign' => $this->activeCampaign
+                       'campaign' => $campaign
                );
 
                $ret = $this->dao->search( $params );
@@ -75,8 +76,7 @@
                $this->view->set( 'pages', $pageCount );
                $this->view->set( 'left', $first );
                $this->view->set( 'right', $last );
-
-               $this->render( 'proposals/queue.html' );
+               $this->render( 'proposals/queue.html', array( 'campaign' => 
$campaign ) );
        }
 
 }
diff --git a/src/Controllers/Proposals/Review.php 
b/src/Controllers/Proposals/Review.php
index 382957f..8f06173 100644
--- a/src/Controllers/Proposals/Review.php
+++ b/src/Controllers/Proposals/Review.php
@@ -47,7 +47,7 @@
        }
 
 
-       protected function handlePost( $id ) {
+       protected function handlePost( $campaign, $id ) {
                $this->form->requireInt( 'proposal' );
                $this->form->requireIntArray( 'points' );
                $this->form->expectStringArray( 'notes' );
@@ -60,7 +60,7 @@
                        );
 
                        $userId = $this->authManager->getUserId();
-                       if ( $this->campaignsDao->isReviewer( 
$this->activeCampaign, $userId) ) {
+                       if ( $this->campaignsDao->isReviewer( $campaign, 
$userId ) ) {
                                $ok = $this->dao->insertOrUpdateReview( $review 
);
                                if ( $ok ) {
                                        $this->flash( 'info', $this->msg( 
'review-edit-save' ) );
@@ -77,7 +77,7 @@
                        // TODO: save input to be shown in get screen
                }
                $this->redirect(
-                       $this->urlFor( 'proposals_view', array( 'id' => $id ) )
+                       $this->urlFor( 'proposals_view', array( 'id' => $id, 
'campaign' => $campaign ) )
                );
        }
 }
diff --git a/src/Controllers/Proposals/Search.php 
b/src/Controllers/Proposals/Search.php
index 7f46655..abe27fe 100644
--- a/src/Controllers/Proposals/Search.php
+++ b/src/Controllers/Proposals/Search.php
@@ -33,10 +33,10 @@
  */
 class Search extends Controller {
 
-       protected function handleGet() {
+       protected function handleGet( $campaign ) {
                $this->form->expectString( 't' );
                $this->form->expectString( 'th' );
-               $this->form->expectString( 'campaign' );
+               $this->form->expectString( 'campaign-select' );
                $this->form->expectInArray( 'stat',
                        array( 'open', 'approved', 'rejected', 'abandoned' ),
                        array( 'default' => 'open' )
@@ -53,13 +53,14 @@
 
                $this->view->set( 't', $this->form->get( 't' ) );
                $this->view->set( 'th', $this->form->get( 'th' ) );
-               $this->view->set( 'campaign', $this->form->get( 'campaign' ) );
+               $this->view->set( 'campaign-select', $this->form->get( 
'campaign-select' ) );
                $this->view->set( 'stat', $this->form->get( 'stat' ) );
                $this->view->set( 'items', $this->form->get( 'items' ) );
                $this->view->set( 'p', $this->form->get( 'p' ) );
                $this->view->set( 's', $this->form->get( 's' ) );
                $this->view->set( 'o', $this->form->get( 'o' ) );
                $this->view->set( 'found', null );
+               $this->view->set( 'campaign', $campaign );
 
                $campaignslist = $this->dao->getCampaigns();
                $this->view->set( 'campaigns', $campaignslist );
@@ -71,7 +72,7 @@
                        $params = array(
                                'title' => $this->form->get( 't' ),
                                'theme' => $this->form->get( 'th' ),
-                               'campaign' => $this->form->get( 'campaign' ),
+                               'campaign' => $this->form->get( 
'campaign-select' ),
                                'status' => $this->form->get( 'stat' ),
                                'sort' => $this->form->get( 's' ),
                                'order' => $this->form->get( 'o' ),
diff --git a/src/Controllers/Proposals/View.php 
b/src/Controllers/Proposals/View.php
index 52b16a8..29cf7b3 100644
--- a/src/Controllers/Proposals/View.php
+++ b/src/Controllers/Proposals/View.php
@@ -52,14 +52,16 @@
                $this->campaignsDao = $dao;
        }
 
-       protected function handleGet( $id ) {
+       protected function handleGet( $campaign, $id ) {
                $proposal = $this->dao->getProposal( $id );
-               $questions = $this->campaignsDao->getQuestions( 
$this->activeCampaign );
+               $questions = $this->campaignsDao->getQuestions( $campaign );
                $this->view->setData( 'proposal', $proposal );
                $this->view->setData( 'questions', $questions );
+               $this->view->set( 'campaign', $campaign );
 
                $userId = $this->authManager->getUserId();
-               $isreviewer = $this->campaignsDao->isReviewer( 
$this->activeCampaign, $userId );
+               $isreviewer = $this->campaignsDao->isReviewer( $campaign, 
$userId );
+
                if ( $isreviewer ) {
                        $review = $this->reviewsDao->reviewByUser( $id );
                        $myReview = array();
diff --git a/src/Controllers/Reports/AbstractReport.php 
b/src/Controllers/Reports/AbstractReport.php
index 78ccbb4..ce71593 100644
--- a/src/Controllers/Reports/AbstractReport.php
+++ b/src/Controllers/Reports/AbstractReport.php
@@ -48,7 +48,7 @@
        /**
         * @return stdClass Results object
         */
-       abstract protected function runReport();
+       abstract protected function runReport( $campaign );
 
        /**
         * Configure the form.
@@ -87,7 +87,7 @@
                return 'asc';
        }
 
-       protected function handleGet() {
+       protected function handleGet( $campaign ) {
                $this->setupForm();
                $this->form->validate( $_GET );
 
@@ -97,8 +97,9 @@
                $this->view->set( 'p', $this->form->get( 'p' ) );
                $this->view->set( 's', $this->form->get( 's' ) );
                $this->view->set( 'o', $this->form->get( 'o' ) );
+               $this->view->set( 'campaign', $campaign );
 
-               $this->view->setData( 'report', $this->runReport() );
+               $this->view->setData( 'report', $this->runReport( $campaign ) );
                $this->render( $this->getTemplate() );
        }
 
diff --git a/src/Controllers/Reports/Aggregated.php 
b/src/Controllers/Reports/Aggregated.php
index 9a0470e..5fb5251 100644
--- a/src/Controllers/Reports/Aggregated.php
+++ b/src/Controllers/Reports/Aggregated.php
@@ -110,7 +110,7 @@
        /**
         * @return stdClass Results
         */
-       protected function runReport() {
+       protected function runReport( $campaign ) {
                $params = array(
                        'sort' => $this->form->get( 's' ),
                        'order' => $this->form->get( 'o' ),
@@ -118,7 +118,7 @@
                        'page' => $this->form->get( 'p' ),
                );
                return $this->dao->aggregatedScores(
-                       $this->activeCampaign, $this->getQuestions(), $params
+                       $campaign, $this->getQuestions(), $params
                );
        }
 
diff --git a/src/Controllers/Reports/Campaigns.php 
b/src/Controllers/Reports/Campaigns.php
index 16815d4..99e0c72 100644
--- a/src/Controllers/Reports/Campaigns.php
+++ b/src/Controllers/Reports/Campaigns.php
@@ -61,7 +61,7 @@
        /**
         * @return stdClass Results
         */
-       protected function runReport() {
+       protected function runReport( $campaign ) {
                $params = array(
                        'sort' => $this->form->get( 's' ),
                        'order' => $this->form->get( 'o' ),
diff --git a/src/Controllers/Reports/Wikitext.php 
b/src/Controllers/Reports/Wikitext.php
index 6d265cd..ac831a5 100644
--- a/src/Controllers/Reports/Wikitext.php
+++ b/src/Controllers/Reports/Wikitext.php
@@ -41,16 +41,16 @@
        }
 
 
-       protected function getQuestions() {
+       protected function getQuestions( $campaign ) {
                static $questions = null;
                if ( $questions === null ) {
-                       $questions = $this->campaignsDao->getQuestions( 
$this->activeCampaign );
+                       $questions = $this->campaignsDao->getQuestions( 
$campaign );
                }
                return $questions;
        }
 
 
-       protected function handleGet() {
+       protected function handleGet( $campaign ) {
                $this->form->expectString( 'th' );
                $this->form->validate( $_GET );
 
@@ -58,14 +58,14 @@
                        'theme' => $this->form->get( 'th' ),
                );
                $records = $this->dao->export(
-                       $this->activeCampaign, $this->getQuestions(), $params
+                       $campaign, $this->getQuestions( $campaign ), $params
                );
                $template = $this->campaignsDao->getTemplate( 
$this->activeCampaign );
                // HACK: map questions to A, B, C, D criteria labels for use in 
output
                // template.
                // FIXME: find a better way to associate questions and the 
wikitext
                $questions = array();
-               foreach( $this->getQuestions() as $q ) {
+               foreach( $this->getQuestions( $campaign ) as $q ) {
                        if( $q['type'] === 'score' ) {
                                $questions[] = "q{$q['id']}";
                        }
@@ -76,6 +76,7 @@
                $this->view->setData( 'report', $records );
                $this->view->set( 'th', $this->form->get( 'th' ) );
                $this->view->set( 'template', $template['wikitext'] );
+               $this->view->set( 'campaign', $campaign );
                $this->render( 'reports/wikitext.html' );
        }
 }
diff --git a/src/Controllers/User/ChangePassword.php 
b/src/Controllers/User/ChangePassword.php
index 7d5e659..e68d722 100644
--- a/src/Controllers/User/ChangePassword.php
+++ b/src/Controllers/User/ChangePassword.php
@@ -33,8 +33,16 @@
  */
 class ChangePassword extends Controller {
 
+       protected $campaignsDao;
+
+
+       public function setCampaignsDao( $dao ) {
+               $this->campaignsDao = $dao;
+       }
+
        protected function handleGet() {
                $this->view->set( 'user', $this->authManager->getUser() );
+               $this->view->set( 'listcampaigns', 
$this->campaignsDao->getUserCampaigns() );
                $this->render( 'user/changePassword.html' );
        }
 
diff --git a/src/Dao/Campaigns.php b/src/Dao/Campaigns.php
index a62b952..906e550 100644
--- a/src/Dao/Campaigns.php
+++ b/src/Dao/Campaigns.php
@@ -58,12 +58,23 @@
        }
 
        /**
+        * Get campaign data for given campaign ID
         * @param int $id ID of campaign whose data is to be fetched
         */
        public function getCampaign( $id ) {
                return $this->fetch(
                        'SELECT * FROM campaigns WHERE id = ?',
                        array( $id )
+               );
+       }
+
+
+       /**
+        * Get all data for all campaigns
+        */
+       public function getAllCampaigns() {
+               return $this->fetchAll(
+                       'SELECT * FROM campaigns ORDER BY status DESC, id ASC'
                );
        }
 
@@ -100,6 +111,19 @@
 
 
        /**
+        * Return all campaigns the current user has been approved to access
+        */
+       public function getUserCampaigns() {
+               $user = $this->userId;
+               $sql = self::concat(
+                       'SELECT cu.campaign_id, cu.user_id, c.name, c.id, 
c.status FROM campaign_users cu',
+                       'INNER JOIN campaigns c ON c.id = cu.campaign_id',
+                       'WHERE cu.user_id = ?'
+               );
+               return $this->fetchAll( $sql, array( $user ) );
+       }
+
+       /**
         * @param int $id Fetches reviewers registered in the system
         * If no parameter is passed, all registered reviewers are returned
         */

-- 
To view, visit https://gerrit.wikimedia.org/r/206844
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I4b36a9ab61eb40b5e4ae86305fb08db65cf26f3e
Gerrit-PatchSet: 18
Gerrit-Project: wikimedia/iegreview
Gerrit-Branch: master
Gerrit-Owner: Niharika29 <[email protected]>
Gerrit-Reviewer: BryanDavis <[email protected]>
Gerrit-Reviewer: Niharika29 <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to