diff --git a/plugins/Directory/DirectoryPlugin.php b/plugins/Directory/DirectoryPlugin.php index aaa33a1ec1..8fd7785ec9 100644 --- a/plugins/Directory/DirectoryPlugin.php +++ b/plugins/Directory/DirectoryPlugin.php @@ -55,7 +55,6 @@ class DirectoryPlugin extends Plugin */ function initialize() { - $this->dir = dirname(__FILE__); return true; } @@ -82,14 +81,20 @@ class DirectoryPlugin extends Plugin { // common_debug("class = $cls"); + $dir = dirname(__FILE__); + switch ($cls) { case 'UserdirectoryAction': - include_once $this->dir + include_once $dir . '/actions/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; return false; case 'AlphaNav': - include_once $this->dir + include_once $dir + . '/lib/' . strtolower($cls) . '.php'; + return false; + case 'SortableSubscriptionList': + include_once $dir . '/lib/' . strtolower($cls) . '.php'; return false; default: diff --git a/plugins/Directory/actions/userdirectory.php b/plugins/Directory/actions/userdirectory.php index 7e9f20c369..7b8dbbdf60 100644 --- a/plugins/Directory/actions/userdirectory.php +++ b/plugins/Directory/actions/userdirectory.php @@ -120,6 +120,9 @@ class UserdirectoryAction extends Action $this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1; $this->filter = $this->arg('filter') ? $this->arg('filter') : 'all'; + $this->sort = $this->arg('sort'); + $this->order = $this->boolean('asc'); // ascending or decending + common_set_returnto($this->selfUrl()); return true; @@ -192,7 +195,7 @@ class UserdirectoryAction extends Action $cnt = 0; if (!empty($profile)) { - $profileList = new SubscriptionList( + $profileList = new SortableSubscriptionList( $profile, common_current_user(), $this @@ -235,7 +238,10 @@ class UserdirectoryAction extends Action ); } - $profile->orderBy('created DESC, nickname'); + $sort = $this->getSortKey(); + $order = ($this->order) ? 'ASC' : 'DESC'; + + $profile->orderBy("$sort $order, nickname"); $profile->limit($limit, $offset); $profile->find(); @@ -243,6 +249,25 @@ class UserdirectoryAction extends Action return $profile; } + /** + * Filter the sort parameter + * + * @return string a column name for sorting + */ + function getSortKey() + { + switch ($this->sort) { + case 'nickname': + return $this->sort; + break; + case 'created': + return $this->sort; + break; + default: + return 'nickname'; + } + } + /** * Show a nice message when there's no search results */ diff --git a/plugins/Directory/css/directory.css b/plugins/Directory/css/directory.css index 3778525a84..76c9fc2583 100644 --- a/plugins/Directory/css/directory.css +++ b/plugins/Directory/css/directory.css @@ -32,3 +32,33 @@ div#user_directory div.alpha_nav a:hover { div#user_directory div.alpha_nav a.current { background-color:#9BB43E; } + +table.profile_list { + width: 100%; +} + +table.profile_list tr { + float: none; +} + +table.profile_list tr.alt { + background-color: #def; /* zebra stripe */ +} + +table.profie_list td { + width: 100%; + padding: 0; +} + + +th.current { + background-image: url(../images/control_arrow_down.gif); + background-repeat: no-repeat; + background-position: 60% 2px; +} + +th.current.asc { + background-image: url(../images/control_arrow_up.gif); + background-repeat: no-repeat; + background-position: 60% 2px; +} \ No newline at end of file diff --git a/plugins/Directory/images/control_arrow_down.gif b/plugins/Directory/images/control_arrow_down.gif new file mode 100644 index 0000000000..de28df6eb0 Binary files /dev/null and b/plugins/Directory/images/control_arrow_down.gif differ diff --git a/plugins/Directory/images/control_arrow_up.gif b/plugins/Directory/images/control_arrow_up.gif new file mode 100644 index 0000000000..898aa604bb Binary files /dev/null and b/plugins/Directory/images/control_arrow_up.gif differ diff --git a/plugins/Directory/lib/alphanav.php b/plugins/Directory/lib/alphanav.php index 6829f3d2c3..33380b0b2b 100644 --- a/plugins/Directory/lib/alphanav.php +++ b/plugins/Directory/lib/alphanav.php @@ -27,7 +27,7 @@ * @link http://status.net/ */ -if (!defined('STATUSNET') && !defined('LACONICA')) { +if (!defined('STATUSNET')) { exit(1); } @@ -114,11 +114,22 @@ class AlphaNav extends Widget ); $params = array('href' => $href); + + // sort column + if (!empty($this->action->sort)) { + $params['sort'] = $this->action->sort; + } + + // sort order + if (!empty($this->action->order)) { + $params['asc'] = 'true'; + } + $current = $this->action->arg('filter'); // Highlight the selected filter. If there is no selected // filter, highlight the first filter in the list - if (empty($current) && $i == 0 + if (!isset($current) && $i == 0 || $current === strtolower($filter)) { $classes .= 'current '; } diff --git a/plugins/Directory/lib/sortablesubscriptionlist.php b/plugins/Directory/lib/sortablesubscriptionlist.php new file mode 100644 index 0000000000..2a412a628d --- /dev/null +++ b/plugins/Directory/lib/sortablesubscriptionlist.php @@ -0,0 +1,248 @@ +. + * + * @category Public + * @package StatusNet + * @author Zach Copley + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/subscriptionlist.php'; + +/** + * Widget to show a sortable list of subscriptions + * + * @category Public + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class SortableSubscriptionList extends SubscriptionList +{ + /** Owner of this list */ + var $owner = null; + + function __construct($profile, $owner=null, $action=null) + { + parent::__construct($profile, $owner, $action); + + $this->owner = $owner; + } + + function startList() + { + $this->out->elementStart('table', array('class' => 'profile_list xoxo')); + $this->out->elementStart('thead'); + $this->out->elementStart('tr'); + + $tableHeaders = array( + 'nickname' => _m('Nickname'), + 'created' => _m('Created') + ); + + foreach ($tableHeaders as $id => $label) { + $attrs = array('id' => $id); + + $current = (!empty($this->action->sort) && $this->action->sort == $id); + + if ($current || empty($this->action->sort) && $id == 'nickname') { + $attrs['class'] = 'current'; + } + + if ($current && !$this->action->boolean('asc')) { + $attrs['class'] .= ' asc'; + $attrs['class'] = trim($attrs['class']); + } + + $this->out->elementStart('th', $attrs); + + $linkAttrs = array(); + $params = array('sort' => $id); + + if ($current && !$this->action->boolean('asc')) { + $params['asc'] = "true"; + } + + $args = array(); + + $filter = $this->action->arg('filter'); + + if (!empty($filter)) { + $args['filter'] = $filter; + } + + $linkAttrs['href'] = common_local_url( + $this->action->arg('action'), $args, $params + ); + + $this->out->element('a', $linkAttrs, $label); + $this->out->elementEnd('th'); + } + + $this->out->element('th', array('id' => 'subscriptions'), 'Subscriptions'); + $this->out->element('th', array('id' => 'notices'), 'Notices'); + //$this->out->element('th', array('id' => 'controls'), 'Controls'); + + $this->out->elementEnd('tr'); + $this->out->elementEnd('thead'); + + $this->out->elementStart('tbody'); + } + + function endList() + { + $this->out->elementEnd('tbody'); + $this->out->elementEnd('table'); + } + + function showProfiles() + { + $cnt = 0; + + while ($this->profile->fetch()) { + $cnt++; + if($cnt > PROFILES_PER_PAGE) { + break; + } + + $odd = ($cnt % 2 == 0); // for zebra striping + + $pli = $this->newListItem($this->profile, $odd); + $pli->show(); + } + + return $cnt; + } + + function newListItem($profile, $odd) + { + return new SortableSubscriptionListItem($profile, $this->owner, $this->action, $odd); + } +} + +class SortableSubscriptionListItem extends SubscriptionListItem +{ + /** Owner of this list */ + var $owner = null; + + function __construct($profile, $owner, $action, $alt) + { + parent::__construct($profile, $owner, $action); + + $this->alt = $alt; // is this row alternate? + $this->owner = $owner; + } + + function startItem() + { + $attr = array( + 'class' => 'profile', + 'id' => 'profile-' . $this->profile->id + ); + + if ($this->alt) { + $attr['class'] .= ' alt'; + } + + $this->out->elementStart('tr', $attr); + } + + function endItem() + { + $this->out->elementEnd('tr'); + } + + function startProfile() + { + $this->out->elementStart('td', 'entity_profile vcard entry-content'); + } + + function endProfile() + { + $this->out->elementEnd('td'); + } + + function startActions() + { + $this->out->elementStart('td', 'entity_actions'); + $this->out->elementStart('ul'); + } + + function endActions() + { + $this->out->elementEnd('ul'); + $this->out->elementEnd('td'); + } + + function show() + { + if (Event::handle('StartProfileListItem', array($this))) { + $this->startItem(); + if (Event::handle('StartProfileListItemProfile', array($this))) { + $this->showProfile(); + Event::handle('EndProfileListItemProfile', array($this)); + } + + // XXX Add events? + $this->showCreatedDate(); + $this->showSubscriberCount(); + $this->showNoticeCount(); + + if (Event::handle('StartProfileListItemActions', array($this))) { + $this->showActions(); + Event::handle('EndProfileListItemActions', array($this)); + } + $this->endItem(); + Event::handle('EndProfileListItem', array($this)); + } + } + + function showSubscriberCount() + { + $this->out->elementStart('td', 'entry_subscriber_count'); + $this->out->raw($this->profile->subscriberCount()); + $this->out->elementEnd('td'); + } + + function showCreatedDate() + { + $this->out->elementStart('td', 'entry_created'); + $this->out->raw(date('j M Y', strtotime($this->profile->created))); + $this->out->elementEnd('td'); + } + + function showNoticeCount() + { + $this->out->elementStart('td', 'entry_notice_count'); + $this->out->raw($this->profile->noticeCount()); + $this->out->elementEnd('td'); + } + +}