[opw-web] First draft of project ranking screen



commit a630bef6db0d5a14efa280eb900e877ca096f34f
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Sun Mar 9 17:57:20 2014 -0400

    First draft of project ranking screen

 classes/class_module.php                           |    1 +
 lang/en-gb.php                                     |    7 +
 modules/mod_rank_projects.php                      |  184 ++++++++++++++++++++
 schema.sql                                         |    1 +
 skins/easterngreen/html/tpl_rank_projects.html     |   60 +++++++
 .../easterngreen/html/tpl_rank_projects_item.html  |   31 ++++
 6 files changed, 284 insertions(+), 0 deletions(-)
---
diff --git a/classes/class_module.php b/classes/class_module.php
index 608e6dd..440258b 100644
--- a/classes/class_module.php
+++ b/classes/class_module.php
@@ -22,6 +22,7 @@ class module
             array('name' => 'user_profile',      'access' => 'u'),
             array('name' => 'view_programs',     'access' => 'g'),
             array('name' => 'view_projects',     'access' => 'u'),
+            array('name' => 'rank_projects',     'access' => 'u'),
             array('name' => 'program_home',      'access' => 'g'),
             array('name' => 'approve_mentors',   'access' => 'a'),
             array('name' => 'view_participants', 'access' => 'a'),
diff --git a/lang/en-gb.php b/lang/en-gb.php
index 79730da..4200c49 100644
--- a/lang/en-gb.php
+++ b/lang/en-gb.php
@@ -134,6 +134,13 @@ $lang_data = array(
     'mentor_dl_info'        => 'Mentor application deadline: [[dl_mentor]]',
     'to'                    => 'to',
 
+    /* Module: rank_projects */
+    'rank_projects'         => 'Rank applications',
+    'go'                    => 'Go',
+    'no_projects_for_organization' => 'No projects were found for this organization',
+    'applicant'             => 'Applicant',
+    'rank'                  => 'Rank',
+
     /* Module: view_projects */
     'submit_proposal'       => 'Submit a proposal',
     'edit_project'          => 'Edit project',
diff --git a/modules/mod_rank_projects.php b/modules/mod_rank_projects.php
new file mode 100644
index 0000000..b1d8741
--- /dev/null
+++ b/modules/mod_rank_projects.php
@@ -0,0 +1,184 @@
+<?php
+/**
+* Pandora v1
+* @license GPLv3 - http://www.opensource.org/licenses/GPL-3.0
+* @copyright (c) 2012 KDE. All rights reserved.
+*/
+
+if (!defined('IN_PANDORA')) exit;
+
+// Collect some data
+$program_id = 0 + $core->variable('prg', 0);
+$organization_id = 0 + $core->variable('o', 0);
+
+$rankings_save = isset($_POST['rankings_save']);
+
+// Validate program and organization_id ID
+if ($organization_id > 0)
+{
+    $sql = "SELECT COUNT(*) AS count " .
+           "FROM {$db->prefix}organizations o " .
+           "LEFT JOIN {$db->prefix}programs prg " .
+           "ON prg.id = o.program_id " .
+           "WHERE o.id = :organization_id " .
+           "AND prg.id = :program_id " .
+           (!$user->is_admin ? "AND prg.is_active = 1" : "");
+}
+else
+{
+    $sql = "SELECT COUNT(*) AS count " .
+           "FROM {$db->prefix}programs " .
+           "WHERE id = :program_id " .
+           (!$user->is_admin ? "AND is_active = 1" : "");
+}
+
+$row = $db->query($sql,
+                  array('program_id' => $program_id,
+                        'organization_id' => $organization_id),
+                  true);
+
+$user->restrict($row['count'] > 0);
+
+// Get the role of the user
+$user->get_role($program_id, $role, $user_organization_id);
+
+// Non-admins can only rank their own organization
+if (!$user->is_admin)
+    $user->restrict($organization_id == $user_organization_id);
+
+// Only admins and mentors can access
+$user->restrict($role == 'm', true);
+
+if ($user->is_admin)
+    $organization_select = build_organization_select($program_id, $organization_id, false,
+                                                     null, "organizationSelect");
+else
+    $organization_select = null;
+
+if ($organization_id > 0) {
+    $sql = "SELECT * FROM {$db->prefix}projects prj " .
+               "LEFT JOIN {$db->prefix}participants prt " .
+               "ON prj.id = prt.project_id " .
+               "WHERE prj.organization_id = ? " .
+               "AND prt.role = 's'";
+    $list_data = $db->query($sql, $organization_id);
+} else {
+    $list_data = array();
+}
+
+// See if we need to save anything
+if ($rankings_save) {
+    foreach ($list_data as &$row) {
+        $project_id = $row['project_id'];
+        $field_name = 'ranking' . $project_id;
+
+        if (isset($_POST[$field_name])) {
+            $value = trim($_POST[$field_name]);
+            if ($value === '')
+                $new_ranking = -1;
+            else
+                $new_ranking = (float)$value;
+
+            if ($new_ranking < 0)
+                $new_ranking = -1;
+
+            if (abs($new_ranking - $row['ranking']) > 0.001) {
+                $sql = "UPDATE {$db->prefix}projects " .
+                       "SET ranking = :ranking " .
+                       "WHERE id = :project_id";
+                $db->query($sql, array('ranking' => $new_ranking,
+                                       'project_id' => $project_id));
+                $row['ranking'] = $new_ranking;
+            }
+        }
+    }
+}
+
+// Now order the rows - we do this client side for two reasons:
+// because we change values when saving, and so that we can special-case
+// negative values
+
+function compare_rankings($a, $b) {
+    $arank = $a['ranking'];
+    $brank = $b['ranking'];
+
+    if ($arank < 0)
+        return ($brank < 0) ? 0 : 1;
+
+    if ($brank < 0)
+        return ($arank < 0) ? 0 : -1;
+
+    if ($arank < $brank)
+        return -1;
+    else
+        return ($arank == $brank) ? 0 : 1;
+}
+
+usort($list_data, "compare_rankings");
+
+$skin->assign('apprej_visibility', $user->is_admin);
+
+// Set the return URL (needed when approving projects)
+$return_url = urlencode($core->request_uri());
+
+$projects_list = '';
+
+foreach ($list_data as $row)
+{
+    $project_title = htmlspecialchars($row['title']);
+    $project_desc  = htmlspecialchars($row['description']);
+    $username = $row['username'];
+    $profile = $user->profile($username);
+
+    // Trim the title to 60 characters
+    if (strlen($project_title) > 60)
+    {
+        $project_title = trim(substr($project_title, 0, 60)) . '&hellip;';
+    }
+
+    // Trim the description to 150 characters
+    if (strlen($project_desc) > 150)
+    {
+        $project_desc = trim(substr($project_desc, 0, 150)) . '&hellip;';
+    }
+
+    if ($row['ranking'] < 0)
+        $ranking = '';
+    else
+        $ranking = number_format($row['ranking'], 1);
+
+    // Assign data for each project
+    $skin->assign(array(
+        'project_title'         => $project_title,
+        'project_description'   => nl2br($project_desc),
+        'project_applicant'     => $profile,
+        'ranking'               => $ranking,
+        'rankingName'           => 'ranking' . $row['project_id'],
+        'project_url'           => "?q=view_projects&amp;prg={$program_id}&amp;p={$row['id']}",
+        'approve_url'           => "?q=view_projects&amp;a=approve&amp;prg={$program_id}" .
+                                   "&amp;p={$row['id']}&amp;r={$return_url}",
+        'reject_url'            => "?q=view_projects&amp;a=reject&amp;prg={$program_id}" .
+                                   "&amp;p={$row['id']}&amp;r={$return_url}",
+    ));
+
+    $projects_list .= $skin->output('tpl_rank_projects_item');
+}
+
+$title = $lang->get('rank_projects');
+
+// Assign final skin data
+$skin->assign(array(
+    'program_id'            => $program_id,
+    'view_title'            => $title,
+    'organization_select'   => $organization_select,
+    'projects_list'         => $projects_list,
+    'select_visibility'     => $skin->visibility($user->is_admin),
+    'notice_visibility'     => $skin->visibility($organization_id > 0 && count($list_data) == 0),
+    'list_visibility'       => $skin->visibility(count($list_data) > 0)
+));
+
+// Output the module
+$module_title = $title;
+$module_data = $skin->output('tpl_rank_projects');
+
+?>
diff --git a/schema.sql b/schema.sql
index 4fccd07..3688929 100644
--- a/schema.sql
+++ b/schema.sql
@@ -34,6 +34,7 @@ CREATE TABLE `opw_projects` (
   `organization_id` mediumint(6) unsigned,
   `is_accepted` tinyint(1) NOT NULL DEFAULT -1,
   `is_complete` tinyint(1) NOT NULL DEFAULT 0,
+  `ranking` float NOT NULL DEFAULT -1,
   PRIMARY KEY (`id`),
   FOREIGN KEY (`program_id`) REFERENCES `opw_programs`(`id`),
   FOREIGN KEY (`organization_id`) REFERENCES `opw_programs`(`id`)
diff --git a/skins/easterngreen/html/tpl_rank_projects.html b/skins/easterngreen/html/tpl_rank_projects.html
new file mode 100644
index 0000000..5b2ebb2
--- /dev/null
+++ b/skins/easterngreen/html/tpl_rank_projects.html
@@ -0,0 +1,60 @@
+<a href="?q=program_home&amp;prg=[[program_id]]" class="no-decor pull-right top-spacer">
+    <i class="icon-arrow-left"></i>
+    {{project_home}}
+</a>
+
+<h1>[[view_title]]</h1>
+<hr class="hr-head" />
+
+<div class="[[select_visibility]]">
+  [[organization_select]]
+  <button onclick='go_organization(event);' class="btn">{{go}}</button>
+  <script type="text/javascript">
+       function go_organization(e) {
+           e.preventDefault();
+           v = $('#organizationSelect').val();
+           l = document.location;
+           if (/o=\d+/.test(l))
+               new_location = ('' + document.location).replace(/o=\d+/, 'o=' + v);
+           else
+               new_location = l + '&o=' + v;
+           document.location.replace(new_location);
+       }
+    </script>
+</div>
+
+<div class="alert alert-info [[notice_visibility]]">
+    {{no_projects_for_organization}}
+</div>
+
+<div class="[[list_visibility]]">
+    <table class="table table-striped">
+        <thead>
+            <tr>
+                <th style="width:250px">
+                    {{project_title}}
+                </th>
+
+                <th style="width:250px">
+                    {{applicant}}
+                </th>
+
+                <th>
+                    {{description}}
+                </th>
+
+                <th>
+                    {{rank}}
+                </th>
+
+                <th style="width:50px;"></th>
+            </tr>
+        </thead>
+
+        <tbody>
+            [[projects_list]]
+        </tbody>
+    </table>
+
+    <button name="rankings_save" type="submit" class="btn btn-primary">{{save}}</button>
+</div>
diff --git a/skins/easterngreen/html/tpl_rank_projects_item.html 
b/skins/easterngreen/html/tpl_rank_projects_item.html
new file mode 100644
index 0000000..b03c8cf
--- /dev/null
+++ b/skins/easterngreen/html/tpl_rank_projects_item.html
@@ -0,0 +1,31 @@
+<tr>
+    <td>
+        <a href="[[project_url]]">
+            [[project_title]]
+        </a>
+    </td>
+
+    <td>
+        [[project_applicant]]
+    </td>
+
+    <td>
+        [[project_description]]
+    </td>
+
+    <td>
+        <input style="width:50px;" type="text" size="4" value="[[ranking]]" name="[[rankingName]]"></input>
+    </td>
+
+    <td>
+        <div class="align-right [[apprej_visibility]]">
+            <a href="[[approve_url]]" title="{{approve}}">
+                <i class="icon-ok"></i>
+            </a>
+            &nbsp;
+            <a href="[[reject_url]]" title="{{reject}}">
+                <i class="icon-remove"></i>
+            </a>
+        </div>
+    </td>
+</tr>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]