New user profile page and list items in user list

This commit is contained in:
Fergal Moran
2013-07-19 15:58:42 +01:00
parent d52168cb4c
commit 7d2f000e00
17 changed files with 215 additions and 130 deletions

View File

@@ -1,4 +1,3 @@
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.db.models import Count, Q
from tastypie import fields
@@ -75,14 +74,15 @@ class UserResource(BackboneCompatibleResource):
def _patch_resource(self, bundle):
#Handle the patched items from backbone
if bundle.data['following']:
bundle.obj.add_follower(bundle.request.user.get_profile())
activity = ActivityFollow()
activity.user = bundle.request.user.get_profile()
activity.to_user = bundle.obj
activity.save()
else:
bundle.obj.remove_follower(bundle.request.user.get_profile())
if 'following' in bundle.data:
if bundle.data['following']:
bundle.obj.add_follower(bundle.request.user.get_profile())
activity = ActivityFollow()
activity.user = bundle.request.user.get_profile()
activity.to_user = bundle.obj
activity.save()
else:
bundle.obj.remove_follower(bundle.request.user.get_profile())
def obj_update(self, bundle, skip_errors=False, **kwargs):
"""
@@ -95,16 +95,28 @@ class UserResource(BackboneCompatibleResource):
if 'activity_sharing_favourites' in kwargs: del kwargs['activity_sharing_favourites']
if 'activity_sharing_comments' in kwargs: del kwargs['activity_sharing_comments']
self._patch_resource(bundle)
#need to figure out why this is excepting, granted I shouldn't be
#trying to update followers in here but still though.
try:
self._patch_resource(bundle)
except:
pass
return super(UserResource, self).obj_update(bundle, skip_errors, **kwargs)
def dehydrate_description(self, bundle):
return bundle.obj.get_profile_description()
def dehydrate(self, bundle):
del bundle.data['activity_sharing']
del bundle.data['activity_sharing_networks']
bundle.data['display_name'] = bundle.obj.get_nice_name()
bundle.data['avatar_image'] = bundle.obj.get_avatar_image()
if bundle.obj.user.id == bundle.request.user.id:
bundle.data['email'] = bundle.obj.email
bundle.data['first_name'] = bundle.obj.first_name
bundle.data['last_name'] = bundle.obj.last_name
bundle.data['activity_sharing_likes'] = \
self._hydrateBitmapOption(bundle.obj.activity_sharing, UserProfile.ACTIVITY_SHARE_LIKES)
bundle.data['activity_sharing_favourites'] = \

View File

@@ -117,7 +117,8 @@ class UserProfile(_BaseModel):
self.logger.error("Backend: %s" % settings.EMAIL_BACKEND)
def remove_follower(self, user):
self.followers.remove(user)
if user in self.followers:
self.followers.remove(user)
def is_follower(self, user):
try:
@@ -174,13 +175,28 @@ class UserProfile(_BaseModel):
except Exception, ex:
pass
elif avatar_type == 'custom' or avatar_type:
return self.avatar_image.name
return urlparse.urljoin(settings.MEDIA_URL, self.avatar_image.name)
return UserProfile.get_default_avatar_image()
def get_profile_url(self):
return '/user/%s' % (self.slug)
def get_profile_description(self):
try:
if not self.description:
social_account = SocialAccount.objects.filter(user=self.user)[0]
if social_account is not None:
provider = social_account.get_provider_account()
if 'bio' in provider.account.extra_data:
return provider.account.extra_data['bio']
else:
return self.description
except Exception, ex:
pass
return "Too lazy to update my description"
@classmethod
def get_default_avatar_image(cls):
return urlparse.urljoin(settings.STATIC_URL, "img/default-avatar-32.png")

View File

@@ -89,7 +89,10 @@ ul.comment-listing .comment-entry {
width: 32px;
height: 32px;
}
.image-user-profile{
width: 320px;
height: 200px;
}
.social_login_providers {
width: 100%;
float: left;

View File

@@ -1,16 +1,17 @@
// Generated by CoffeeScript 1.3.3
// Generated by CoffeeScript 1.6.2
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['app', 'marionette', 'vent', 'views/chat/chatView', 'models/mix/mixItem', 'views/mix/mixListLayout', 'views/mix/mixListView', 'views/mix/mixDetailView', 'views/mix/mixEditView', 'models/user/userItem', 'views/user/userListView', 'views/user/userEditView'], function(App, Marionette, vent, ChatView, MixItem, MixListLayout, MixListView, MixDetailView, MixEditView, UserItem, UserListView, UserEditView) {
var DssController;
DssController = (function(_super) {
var DssController, _ref;
DssController = (function(_super) {
__extends(DssController, _super);
function DssController() {
return DssController.__super__.constructor.apply(this, arguments);
_ref = DssController.__super__.constructor.apply(this, arguments);
return _ref;
}
DssController.prototype.home = function() {
@@ -21,6 +22,7 @@
DssController.prototype._showMixList = function() {
var app;
app = require('app');
app.contentRegion.show(new MixListLayout());
return true;
@@ -36,6 +38,7 @@
DssController.prototype.showMix = function(slug) {
var app, mix;
console.log("Controller: showMix");
app = require('app');
mix = new MixItem({
@@ -54,6 +57,7 @@
DssController.prototype.uploadMix = function() {
var app, mix;
console.log("Controller: mixUpload");
app = require('app');
mix = new MixItem({
@@ -70,6 +74,7 @@
DssController.prototype.editMix = function(slug) {
var app, mix;
console.log("Controller: mixEdit");
app = require('app');
mix = new MixItem({
@@ -87,6 +92,7 @@
DssController.prototype.showChat = function() {
var app;
console.log("Controller: showChat");
app = require('app');
return app.contentRegion.show(new ChatView());
@@ -94,6 +100,7 @@
DssController.prototype.showUserList = function(type) {
var app;
console.log("Controller: showUserList");
app = require('app');
return app.contentRegion.show(new UserListView());
@@ -150,6 +157,7 @@
DssController.prototype.editUser = function() {
var app, user;
console.log("Controller: editUser");
app = require('app');
user = new UserItem({

View File

@@ -1,16 +1,17 @@
// Generated by CoffeeScript 1.3.3
// Generated by CoffeeScript 1.6.2
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['marionette', 'vent', 'app.lib/controller'], function(Marionette, vent, Controller) {
var DssRouter;
return DssRouter = (function(_super) {
var DssRouter, _ref;
return DssRouter = (function(_super) {
__extends(DssRouter, _super);
function DssRouter() {
return DssRouter.__super__.constructor.apply(this, arguments);
_ref = DssRouter.__super__.constructor.apply(this, arguments);
return _ref;
}
DssRouter.prototype.controller = new Controller;

View File

@@ -48,7 +48,7 @@ define ['moment', 'app', 'vent', 'marionette', 'utils', 'models/comment/commentC
renderGenres: =>
el = @el
$.each @model.get("genre-list"), (data) ->
$("#genre-list", el).append '<a href="/mixes/' + @slug + '" class="dss-tag-button">' + @text + '</a>'
$("#genre-list", el).append '<a href="/mixes/' + @slug + '" class="label label-info">' + @text + '</a>'
true
true

View File

@@ -1,26 +1,22 @@
// Generated by CoffeeScript 1.3.3
// Generated by CoffeeScript 1.6.2
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['moment', 'app', 'vent', 'marionette', 'utils', 'models/comment/commentCollection', 'views/comment/commentListView', 'text!/tpl/MixListItemView'], function(moment, App, vent, Marionette, utils, CommentsCollection, CommentsListView, Template) {
var MixItemView;
MixItemView = (function(_super) {
var MixItemView, _ref;
MixItemView = (function(_super) {
__extends(MixItemView, _super);
function MixItemView() {
this.doStart = __bind(this.doStart, this);
this.renderComments = __bind(this.renderComments, this);
this.renderGenres = __bind(this.renderGenres, this);
this.onRender = __bind(this.onRender, this);
this.initialize = __bind(this.initialize, this);
return MixItemView.__super__.constructor.apply(this, arguments);
this.initialize = __bind(this.initialize, this); _ref = MixItemView.__super__.constructor.apply(this, arguments);
return _ref;
}
MixItemView.prototype.template = _.template(Template);
@@ -54,6 +50,7 @@
MixItemView.prototype.onRender = function() {
var id, totalDuration, totalDurationText;
id = this.model.get('id');
if (this.model.get('duration')) {
totalDuration = moment.duration(this.model.get('duration'), "seconds");
@@ -73,9 +70,10 @@
MixItemView.prototype.renderGenres = function() {
var el;
el = this.el;
$.each(this.model.get("genre-list"), function(data) {
$("#genre-list", el).append('<a href="/mixes/' + this.slug + '" class="dss-tag-button">' + this.text + '</a>');
$("#genre-list", el).append('<a href="/mixes/' + this.slug + '" class="label label-info">' + this.text + '</a>');
return true;
});
return true;
@@ -83,6 +81,7 @@
MixItemView.prototype.renderComments = function() {
var comments;
comments = new CommentsCollection();
comments.url = this.model.get("resource_uri") + "comments/";
comments.mix_id = this.model.id;
@@ -90,6 +89,7 @@
comments.fetch({
success: function(data) {
var content;
console.log(data);
content = new CommentsListView({
collection: comments
@@ -139,6 +139,7 @@
MixItemView.prototype.mixFavourite = function() {
var app;
console.log("MixItemView: favouriteMix");
app = require('app');
vent.trigger("mix:favourite", this.model);
@@ -153,6 +154,7 @@
MixItemView.prototype.mixShare = function(e) {
var mode;
console.log("MixItemView: shareMix");
mode = $(e.currentTarget).data("mode");
console.log("MixItemView: " + mode);

View File

@@ -1,17 +1,19 @@
// Generated by CoffeeScript 1.3.3
// Generated by CoffeeScript 1.6.2
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['marionette', 'vent', 'models/mix/mixCollection', 'views/mix/mixItemView', 'text!/tpl/MixListView'], function(Marionette, vent, MixCollection, MixItemView, Template) {
var MixListView;
var MixListView, _ref;
MixListView = (function(_super) {
var currentMix;
__extends(MixListView, _super);
function MixListView() {
return MixListView.__super__.constructor.apply(this, arguments);
_ref = MixListView.__super__.constructor.apply(this, arguments);
return _ref;
}
MixListView.prototype.template = _.template(Template);
@@ -33,6 +35,7 @@
MixListView.prototype.mixPlay = function(model) {
var v;
if (currentMix !== -1) {
v = this.children.findByModelCid(currentMix);
v.mixStop(v.model);

View File

@@ -8,7 +8,7 @@ define ['app', 'toastr', 'app.lib/editableView', 'moment', 'libs/backbone/backbo
onRender: ->
console.log("MixEditView: onRender")
avatarType = @model.get('profile').avatar_type
avatarType = @model.get('avatar_type')
$('#avatar_' + avatarType, @el).attr('checked', true);
if avatarType is "custom"
$("#div_avatar_image_upload", @el).show()
@@ -32,7 +32,7 @@ define ['app', 'toastr', 'app.lib/editableView', 'moment', 'libs/backbone/backbo
ref = this
@_saveChanges
success: ->
if ref.model.get("profile").avatar_type is "custom"
if ref.model.get('avatar_type') is "custom"
$.ajaxFileUpload
url: "/ajax/upload_avatar_image/"
secureuri: false

View File

@@ -1,16 +1,17 @@
// Generated by CoffeeScript 1.3.3
// Generated by CoffeeScript 1.6.2
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['app', 'toastr', 'app.lib/editableView', 'moment', 'libs/backbone/backbone.syphon', 'text!/tpl/UserEditView'], function(App, toastr, EditableView, moment, Syphon, Template) {
var UserEditView;
UserEditView = (function(_super) {
var UserEditView, _ref;
UserEditView = (function(_super) {
__extends(UserEditView, _super);
function UserEditView() {
return UserEditView.__super__.constructor.apply(this, arguments);
_ref = UserEditView.__super__.constructor.apply(this, arguments);
return _ref;
}
UserEditView.prototype.template = _.template(Template);
@@ -22,8 +23,9 @@
UserEditView.prototype.onRender = function() {
var avatarType;
console.log("MixEditView: onRender");
avatarType = this.model.get('profile').avatar_type;
avatarType = this.model.get('avatar_type');
$('#avatar_' + avatarType, this.el).attr('checked', true);
if (avatarType === "custom") {
$("#div_avatar_image_upload", this.el).show();
@@ -38,6 +40,7 @@
UserEditView.prototype.selectAvatar = function(evt) {
var type;
type = $(evt.currentTarget).val();
this.model.set("avatar_type", type);
if (type === "custom") {
@@ -52,12 +55,13 @@
UserEditView.prototype.saveChanges = function() {
var data, ref;
data = Backbone.Syphon.serialize(this);
this.model.set(data);
ref = this;
this._saveChanges({
success: function() {
if (ref.model.get("profile").avatar_type === "custom") {
if (ref.model.get('avatar_type') === "custom") {
$.ajaxFileUpload({
url: "/ajax/upload_avatar_image/",
secureuri: false,

View File

@@ -2,7 +2,8 @@ define ['app', 'moment', 'marionette', 'vent', 'text!/tpl/UserListItemView'],
(App, moment, Marionette, vent, Template)->
class UserItemView extends Marionette.ItemView
template: _.template(Template)
tagName: "tr"
tagName: "div"
className: "row-fluid"
events:
"click #follow-button": "followUser"

View File

@@ -17,7 +17,9 @@
UserItemView.prototype.template = _.template(Template);
UserItemView.prototype.tagName = "tr";
UserItemView.prototype.tagName = "div";
UserItemView.prototype.className = "row-fluid";
UserItemView.prototype.events = {
"click #follow-button": "followUser",

View File

@@ -11,7 +11,7 @@ define ['jquery', 'marionette', 'models/user/userCollection', 'views/user/userIt
searchText: "#search-text"
itemView: UserItemView
itemViewContainer: "tbody"
itemViewContainer: "#user-table"
initialize: =>
console.log "UserListView: initialize"
@collection = new UserCollection()

View File

@@ -29,7 +29,7 @@
UserListView.prototype.itemView = UserItemView;
UserListView.prototype.itemViewContainer = "tbody";
UserListView.prototype.itemViewContainer = "#user-table";
UserListView.prototype.initialize = function() {
console.log("UserListView: initialize");

View File

@@ -5,23 +5,23 @@
<div id="layout-area" class="hero-well">
<div class="row">
<form enctype="multipart/form-data" method="post" class="form-horizontal" id="id-new-user-form">
<input type="hidden" name="profile[id]" value="<%= profile.id %>"/>
<input type="hidden" name="id" value="<%= id %>"/>
<fieldset>
<div class="span6">
<div class="clearfix control-group" id="div_display_name">
<label class="control-label" for="display_name">Display name</label>
<div class="controls">
<input type="text" maxlength="75" name="profile[display_name]" class="textinput textInput"
id="profile[display_name]"
value="<%= profile.display_name %>">
<input type="text" maxlength="75" name="display_name" class="textinput textInput"
id="display_name"
value="<%= display_name %>">
</div>
</div>
<div class="clearfix control-group" id="div_slug">
<label class="control-label" for="slug">Profile Slug</label>
<div class="controls">
<input type="text" maxlength="75" name="profile[slug]" class="textinput textInput"
id="profile[slug]"
value="<%= profile.slug %>">
<input type="text" maxlength="75" name="slug" class="textinput textInput"
id="slug"
value="<%= slug %>">
</div>
</div>
<div class="clearfix control-group" id="div_email">
@@ -51,9 +51,9 @@
<label class="control-label requiredField" for="avatar_image_select_0">Avatar Image<span
class="asteriskField">*</span></label>
<div class="controls">
<label class="radio">Use gravatar image.<input type="radio" id='avatar_gravatar' value='gravatar' name="profile[avatar_type]" /></label>
<label class="radio">Use Twitter/Facebook image.<input type="radio" id='avatar_social' value='social' name="profile[avatar_type]" /></label>
<label class="radio">Use custom image.<input type="radio" id='avatar_custom' value='custom' name="profile[avatar_type]" /></label>
<label class="radio">Use gravatar image.<input type="radio" id='avatar_gravatar' value='gravatar' name="avatar_type" /></label>
<label class="radio">Use Twitter/Facebook image.<input type="radio" id='avatar_social' value='social' name="avatar_type" /></label>
<label class="radio">Use custom image.<input type="radio" id='avatar_custom' value='custom' name="avatar_type" /></label>
</div>
</div>
<div class="clearfix control-group" id="div_avatar_image_upload">
@@ -62,7 +62,7 @@
<div class="fileupload fileupload-new pull-left" data-provides="fileupload"
id="div_avatar_image">
<div class="fileupload-new thumbnail" style="width: 200px; height: 150px;">
<img src="<%= profile.avatar_image %>"/>
<img src="<%= avatar_image %>"/>
</div>
<div class="fileupload-preview fileupload-exists thumbnail"
style="max-width: 200px; max-height: 150px; line-height: 20px;">
@@ -87,7 +87,7 @@
<p>
<h5>Tell us a bit about yourself.</h5>
</p>
<textarea style="width: 100%" name="profile[description]" id="profile[description]" rows="5"><%= profile.description %></textarea>
<textarea style="width: 100%" name="description" id="description" rows="5"><%= description %></textarea>
</div>
<div class="row">
<p>
@@ -104,16 +104,16 @@
</tr>
<tr>
<td>
<input type="checkbox" name="profile[activity_sharing_likes]"
id="activity_sharing_likes" <%= renderCheckbox(profile.activity_sharing_likes) %>>
<input type="checkbox" name="activity_sharing_likes"
id="activity_sharing_likes" <%= renderCheckbox(activity_sharing_likes) %>>
</td>
<td>
<input type="checkbox" name="profile[activity_sharing_favourites]"
id="activity_sharing_favourites" <%= renderCheckbox(profile.activity_sharing_favourites) %>>
<input type="checkbox" name="activity_sharing_favourites"
id="activity_sharing_favourites" <%= renderCheckbox(activity_sharing_favourites) %>>
</td>
<td>
<input type="checkbox" name="profile[activity_sharing_comments]"
id="activity_sharing_comments" <%= renderCheckbox(profile.activity_sharing_comments) %>>
<input type="checkbox" name="activity_sharing_comments"
id="activity_sharing_comments" <%= renderCheckbox(activity_sharing_comments) %>>
</td>
</tr>
</tbody>
@@ -129,10 +129,10 @@
</tr>
<tr>
<td style="text-align: center; vertical-align: middle">
<input type="checkbox" name="profile[activity_sharing_networks_facebook]" <%= renderCheckbox(profile.activity_sharing_networks_facebook) %>>
<input type="checkbox" name="activity_sharing_networks_facebook" <%= renderCheckbox(activity_sharing_networks_facebook) %>>
</td>
<td>
<input type="checkbox" name="profile[activity_sharing_networks_twitter]" <%= renderCheckbox(profile.activity_sharing_networks_twitter) %>>
<input type="checkbox" name="activity_sharing_networks_twitter" <%= renderCheckbox(activity_sharing_networks_twitter) %>>
</td>
</tr>
</tbody>

View File

@@ -1,34 +1,83 @@
<td>
<a href="<%= url %>"><%= display_name %></a>
</td>
<td>
<a href="/user/<%= slug %>"><%= mix_count%></a>
</td>
<td>
<a href="/user/<%= slug %>/likes"><%= like_count%></a>
</td>
<td>
<a href="/user/<%= slug %>/favourites"><%= favourite_count%></a>
</td>
<td>
<a href="/user/<%= slug %>/followers"><%= follower_count %></a>
</td>
<td><%= following_count %></td>
<td><%= humanise(date_joined) %></td>
<td><%= humanise(last_login) %></td>
<div class="span12 bordered-faint well">
<div class="row-fluid">
<ul class="inline">
<li>
{% if user.is_authenticated %}
<button href="#"
id="follow-button"
class="follow-button btn btn-mini btn-primary icon <% if (following) { %> disabled <% } %>">
<i id="follow-icon" class="icon-eye-close"></i>Follow
</button>
{% else %}
<button href="#"
id="follow-button-login"
class="follow-button btn btn-mini btn-primary icon <% if (following) { %> disabled <% } %>">
<i id="follow-icon" class="icon-eye-close"></i>Follow
</button>
{% endif %}
</li>
<li>
<h4><strong><a href="<%= url %>"><%= display_name %></a></strong>
</h4>
</li>
</ul>
</div>
<div class="row-fluid">
<div class="span2">
<a href="<%= url %>" class="thumbnail">
<img src="<%= avatar_image %>" alt="" style="width: 170px; height: 106px">
</a>
</div>
<div class="span6">
<p>
<%= description %>
</p>
</div>
</div>
<div class="row-fluid">
<div class="span8">
<p></p>
<td>
{% if user.is_authenticated %}
<button href="#"
id="follow-button"
class="follow-button btn btn-mini <% if (following) { %> disabled <% } %>">
<i id="follow-icon" class="icon-eye-close"></i>Follow
</button>
{% else %}
<button href="#"
id="follow-button-login"
class="follow-button btn btn-mini <% if (following) { %> disabled <% } %>">
<i id="follow-icon" class="icon-eye-close"></i>Follow
</button>
{% endif %}
</td>
<p>
| <i class="icon-calendar"></i> Joined: <%= humanise(date_joined) %>
| <i class="icon-calendar"></i> Last Seen: <%= humanise(last_login) %>
</p>
<p>
| <i class="icon-comment"></i> <a href="/user/<%= slug %>"><%= mix_count%> Mixes</a>
| <i class="icon-share"></i> <a href="/user/<%= slug %>/favourites"><%= favourite_count %>
Favourites</a>
| <i class="icon-share"></i> <a href="/user/<%= slug %>/likes"><%= like_count %> Likes</a>
| <i class="icon-share"></i> <a href="#"><%= follower_count %> Followers</a>
| <i class="icon-share"></i> <a href="#"><%= following_count %> Following</a>
</p>
</div>
</div>
</div>
<!--
<div class="thumbnail clearfix">
<img src="<%= avatar_image %>" alt="ALT NAME" class="pull-left span2 clearfix"
style='margin-right:10px; width: 170px; height: 106px'>
<div class="caption">
{% if user.is_authenticated %}
<button href="#"
id="follow-button"
class="follow-button btn btn-primary icon pull-right <% if (following) { %> disabled <% } %>">
<i id="follow-icon" class="icon-eye-close"></i>Follow
</button>
{% else %}
<button href="#"
id="follow-button-login"
class="follow-button btn btn-primary icon pull-right <% if (following) { %> disabled <% } %>">
<i id="follow-icon" class="icon-eye-close"></i>Follow
</button>
{% endif %}
<h4>
<a href="<%= url %>"><%= display_name %></a>
</h4>
<small><%= description %></small>
</div>
</div>
-->

View File

@@ -1,31 +1,15 @@
<div class="user-list-container">
<table id="user-table" class="table table-striped table-bordered datagrid" style="overflow: scroll">
<thead>
<tr>
<th colspan="7">
<div class="pull-left">
<div class="input-append search datagrid-search">
<input id="search-text" type="text" class="input-large" placeholder="Search">
<button type="button" class="btn"><i class="icon-search"></i></button>
</div>
</div>
<div class="pull-right">
<div id="page-selection"></div>
</div>
</th>
</tr>
<tr class="warning">
<th>Name</th>
<th>Uploads</th>
<th>Likes</th>
<th>Favourites</th>
<th>Followers</th>
<th>Following</th>
<th>Join date</th>
<th>Last seen</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody></tbody>
</table>
<div class="user-list-header row-fluid">
<div class="pull-left span6">
<div class="input-append search datagrid-search">
<input id="search-text" type="text" class="input-large" placeholder="Search">
<button type="button" class="btn"><i class="icon-search"></i></button>
</div>
</div>
<div class="pull-right span6">
<div id="page-selection"></div>
</div>
</div>
<hr>
<div class="user-list-details row-fluid" id="user-table">
</div>