Hello,

So after digging around the thread and API for a little while, I'm still a bit puzzled at figuring out a "clean" way of theming PrivateMsg. It seems there are no classes for the message listing table (?)

So far I got it to look like gmail (screenshot attached), but I had to modify three lines in the module core.

Here's the basic idea:

#1. Add message body through API (custom module or phptemplate)

function helper123_privatemsg_sql_list_alter(&$fragments, $account) {
	$fragments['select'][] = 'pm.body'; // load 'body' into $row in theme_privatemsg_message_row()
}
function helper123_privatemsg_sql_list_sent_alter(&$fragments, $account) {
	$fragments['select'][] = 'pm.body'; // load 'body' into $row in theme_privatemsg_message_row()
}

#2. Customize the message listing output (phptemplate)

function phptemplate_privatemsg_message_row($row) {
  $themed_row = array();

  $unread = '';
  if (isset($row['is_new']) && $row['is_new'] ) {
    $unread = ' privatemsg-unread';
  }
  if (isset($row['author']) && $row['author']) {
    $authors = _privatemsg_generate_user_array($row['author']);
    $themed_row[t('Authors')] = array('data' => '<span class="privatemsg-list-from'.  $unread .'">'. _privatemsg_format_participants($authors, 3, TRUE) .'</span>', 'class' => 'Authors');
  }
  if (array_key_exists('recipient', $row)) {
    $themed_row[t('Recipients')] = '';
    if (!empty($row['recipient'])) {
      $recipients = _privatemsg_generate_user_array($row['recipient']);
      $themed_row[t('Recipients')] = array('data' => '<span class="privatemsg-list-to'.  $unread .'">'. _privatemsg_format_participants($recipients, 3, TRUE) .'</span>', 'class' => 'Recipients');
    }
  }
  if (array_key_exists('body', $row)) {
    $body = ' - <span class="privatemsg-list-body">'. substr($row['body'], 0, 150) .'</span>';
  }
  $themed_row[t('Subject')] = array('data' => '<span class="privatemsg-list-subject'. $unread .'">'. l($row['subject'], 'messages/view/'. $row['thread_id']) .'</span>'.$body, 'class' => 'Subject');

  if ($row['last_updated']) {
	//$themed_row[t('Last updated')] = '<span class="privatemsg-list-date'.  $unread .'">'. format_date($row['last_updated'], 'small') .'</span>';
	$time_ago = time() - $row['last_updated'];
	$themed_row[t('Last updated')] = array('data' => '<span class="privatemsg-list-date'.  $unread .'">'. format_interval($time_ago,1) .' ago</span>', 'class' => 'Last-updated');
	
  }
  //drupal_set_message(var_export($themed_row,true));
  //return $themed_row;
  return array('data' => $themed_row, 'class' => $unread);
}

#3. Modify module core (I'd like to avoid this somehow)

Since we're converting simple rows into complex rows, we need to read the 'data' in the array.
find this line:

foreach (array_keys($rows[0]) as $index) {

... and replace with this:

foreach (array_keys($rows[0]['data']) as $index) {

Add some table heading classes:
find this line:

$head[$index] =  array('data' => $index);

... and replace with this:

$head[$index] =  array('data' => $index, 'class' => preg_replace('/[^a-z0-9_-]/i','-',$index));

Question: Is there a better way to add syntax-safe classes here than preg_replace?

Add a table class
find this line:

$content = theme('table', $head, $rows);

... and replace it with this:

$content = theme('table', $head, $rows, array('class' => 'privatemsg-list'));

The message listing table is now fully themeable.

I have a deadline on this particular project, so I didn't have time to look too deeply into alternatives, but I'd love to hear some ideas about improvements on this and on how to avoid modifying the module core to achieve the same.

Best,
Andrey.

CommentFileSizeAuthor
#3 images.zip2.12 KBmr.andrey
privatemsg-gmail.jpg99.01 KBmr.andrey

Comments

berdir’s picture

This looks great!

I'm sure we can find a way to allow this without making changes to the core, I am working on restructuring the list display, which should already eliminate some of your problems. I'll explain it later in #348907: Per thread/Multiple thread actions in detail.

A very short feedback, will come back on you later when the mentioned issue above is working.

#1: This might not work on more strict sql servers like postgresql, I need to check that..

#2: I changed from a simple string to an array just a few hours ago. I did more or less the same as you and added the unread class to the tr tag and moved the span classes to td. I'll explain it in detail later.

#3: I'll add default css classes to the table and the headers...

Would it be possible for you to share your theme modifications so that we could include it as a selectable theme?

mr.andrey’s picture

Great. Looking forward to hearing about your progress.

Sure, here is the CSS and images are attached:

/* listing */
#privatemsg-filter-dropdown fieldset {
	padding-bottom:0;
}
span.privatemsg-unread {
	font-weight: bold;
}
.privatemsg-list-body {
	color: #777;
}
.privatemsg-list {
	width:100%;
	margin:0;
}
.privatemsg-list th {
	padding-left:5px;
}
.privatemsg-list td {
	white-space:nowrap;
	overflow:hidden;
	max-width:200px;
	padding-left:5px;
}
.privatemsg-list th.Authors {
	width: 150px;
}
.privatemsg-list th.Subject {
	/* keep flexible */
}
.privatemsg-list th.Last-updated {
	width:100px;
}
/* end listing */
/* bubble */
.privatemsg-list {
	border:0;
}
.privatemsg-list th.Authors,
.privatemsg-list th.Recipients {
	background: url('images/block_bubble_white_top.gif') no-repeat top left;
	padding-left:10px;
}
.privatemsg-list td.Authors,
.privatemsg-list td.Recipients{
	background: url('images/block_bubble_white_bg.gif') repeat-y left;
	padding-left:10px;
}
.privatemsg-list .privatemsg-unread td.Authors,
.privatemsg-list .privatemsg-unread td.Recipients {
	background: url('images/block_bubble_yellow_bg.gif') repeat-y left;
	padding-left:10px;
}
.privatemsg-list th {
	background: url('images/block_bubble_white_top.gif') no-repeat top center;
	border-bottom: 1px solid #ccd9e6;
}
.privatemsg-list .privatemsg-unread td {
	background: url('images/block_bubble_yellow_bg.gif') repeat-y center;
}
.privatemsg-list th.Last-updated {
	background: url('images/block_bubble_white_top.gif') no-repeat top right;
	padding-right:10px;
}
.privatemsg-list td.Last-updated {
	background: url('images/block_bubble_white_bg.gif') repeat-y right;
	padding-right:10px;
}
.privatemsg-list .privatemsg-unread td.Last-updated {
	background: url('images/block_bubble_yellow_bg.gif') repeat-y right;
	padding-right:10px;
}
/* end bubble */

I assume you don't need the custom tabs, but if you do, here's the thread with template and all:
#372958: Solution for tabs/QuickTabs that works in IE6, IE7, Firefox 3 and Safari 3 identically

Best,
Andrey.

mr.andrey’s picture

StatusFileSize
new2.12 KB

For some reason the file didn't attach. Trying again.

mr.andrey’s picture

Here's a more IE6&7-friendly version (apparently IE needs a div for the gmail-style body overflow to work correctly without breaking lines):

function phptemplate_privatemsg_message_row($row) {
  $themed_row = array();

  $unread = '';
  if (isset($row['is_new']) && $row['is_new'] ) {
    $unread = ' privatemsg-unread';
  }
  if (isset($row['author']) && $row['author']) {
    $authors = _privatemsg_generate_user_array($row['author']);
    $themed_row[t('Authors')] = array('data' => '<span class="privatemsg-list-from'.  $unread .'">'. _privatemsg_format_participants($authors, 3, TRUE) .'</span>', 'class' => 'Authors');
  }
  if (array_key_exists('recipient', $row)) {
    $themed_row[t('Recipients')] = '';
    if (!empty($row['recipient'])) {
      $recipients = _privatemsg_generate_user_array($row['recipient']);
      $themed_row[t('Recipients')] = array('data' => '<span class="privatemsg-list-to'.  $unread .'">'. _privatemsg_format_participants($recipients, 3, TRUE) .'</span>', 'class' => 'Recipients');
    }
  }
  if (array_key_exists('body', $row)) {
    $body = '<span class="privatemsg-list-body"> - '. substr($row['body'], 0, 250) .'</span>';
  }
  $themed_row[t('Subject')] = array('data' => '<div class="privatemsg-list-subject-body"><span class="privatemsg-list-subject'. $unread .'">'. l($row['subject'], 'messages/view/'. $row['thread_id']) .'</span>'.$body.'</div>', 'class' => 'Subject');

  if ($row['last_updated']) {
	//$themed_row[t('Last updated')] = '<span class="privatemsg-list-date'.  $unread .'">'. format_date($row['last_updated'], 'small') .'</span>';
	$time_ago = time() - $row['last_updated'];
	$themed_row[t('Last updated')] = array('data' => '<span class="privatemsg-list-date'.  $unread .'">'. format_interval($time_ago,1) .' ago</span>', 'class' => 'Last-updated');
	
  }
  //drupal_set_message(var_export($themed_row,true));
  //return $themed_row;
  return array('data' => $themed_row, 'class' => $unread);
}
/* listing */
#privatemsg-filter-dropdown fieldset {
	padding-bottom:5px;
}
span.privatemsg-unread {
	font-weight: bold;
}
.privatemsg-list-body {
	color: #777;
}
.privatemsg-list {
	margin:0;
}
.privatemsg-list th {
	padding-left:5px;
}
.privatemsg-list td {
	white-space:nowrap;
	overflow:hidden;
	padding-left:5px;
	width:480px;
}
.privatemsg-list td div.privatemsg-list-subject-body {
	overflow:hidden;
	white-space:nowrap;
	width:480px;
}
.privatemsg-list th.Authors {
	width: 150px;
}
.privatemsg-list th.Subject {
	/* keep flexible */
}
.privatemsg-list th.Last-updated {
	width:100px;
}
/* end listing */
/* bubble */
.privatemsg-list {
	border:0;
}
.privatemsg-list th.Authors,
.privatemsg-list th.Recipients {
	background: url('images/block_bubble_white_top.gif') no-repeat top left;
	padding-left:10px;
}
.privatemsg-list td.Authors,
.privatemsg-list td.Recipients{
	background: url('images/block_bubble_white_bg.gif') repeat-y left;
	padding-left:10px;
}
.privatemsg-list .privatemsg-unread td.Authors,
.privatemsg-list .privatemsg-unread td.Recipients {
	background: url('images/block_bubble_yellow_bg.gif') repeat-y left;
	padding-left:10px;
}
.privatemsg-list th {
	background: url('images/block_bubble_white_top.gif') no-repeat top center;
	border-bottom: 1px solid #ccd9e6;
}
.privatemsg-list .privatemsg-unread td {
	background: url('images/block_bubble_yellow_bg.gif') repeat-y center;
}
.privatemsg-list th.Last-updated {
	background: url('images/block_bubble_white_top.gif') no-repeat top right;
	padding-right:10px;
}
.privatemsg-list td.Last-updated {
	background: url('images/block_bubble_white_bg.gif') repeat-y right;
	padding-right:10px;
}
.privatemsg-list .privatemsg-unread td.Last-updated {
	background: url('images/block_bubble_yellow_bg.gif') repeat-y right;
	padding-right:10px;
}
/* end bubble */
sansui’s picture

Looks great, but I'm unable to find the lines to change in the current dev code. Perhaps the module has changed significantly since this posting

litwol’s picture

Status: Active » Needs work

*alot* have changed.

berdir’s picture

If we want this in privatemsg, we need some sort of styles support, similiar to advanced forum or panels. advanced forum styles are explained at http://drupal.org/node/512116.

Note that this is definitly post 1.0 but of course, if someone is interested to implement this, feel free to do so.

berdir’s picture

Category: support » feature

Setting the correct category, this is a new feature, not a support request.

Bilmar’s picture

subscribing - I am very interested in being able to have full control over privatemsg as discussed in this thread.

berdir’s picture

You already have, see http://blog.worldempire.ch/de/api/group/theming/1 for more information.

This issue is just about providing different themes with privatemsg.module and the ability to choose between them in the admin UI.

Bilmar’s picture

my apologies Berdir -

I am trying to change 'Participants' to 'From' and use field_firstname from content profile, and customize the 'Write new message' page but read about problems with page-messages-new.tpl.php

I will study the link you provided above

Thanks

berdir’s picture

field_firstname from content profile

Privatemsg should always use theme_username(). However, you might not always have full user objects, especially when displaying a thread (for performance reasons). You can either use user_load() to load the full user or extend the participants query so that it does directly load and return that field (a bit more complicated but better performance). See:

- http://blog.worldempire.ch/api/group/sql/1
- http://blog.worldempire.ch/api/function/privatemsg_sql_participants/1

I am trying to change 'Participants' to 'From'

On the view page? That is a bit tricky because that comes from a function, not a theme: http://blog.worldempire.ch/api/function/_privatemsg_format_participants/1. However, since it's a translated string, you can use string overrides to do that: http://drupal.org/project/stringoverrides

page-messages-new.tpl.php

That is a completely different thing, that would be a template suggestion for the *whole* page at messages/new. But you can't use that to change parts of the page.

Bilmar’s picture

Thank you - I was able to successfully change 'Participants' to 'From' using stringoverrides!

I'm currently using email registration module so the username field is hidden at registration and auto set to everything before the @example.com
Therefore, I would like to use field_firstname from cck/content profile (username isn't a variable I have been using on the website)

I have used the below code in .tpl.php files before. Is there something similar I can use to have the 'Participants' column show this field instead of username for each message thread?

  $a = $content_profile->get_variable('profile', 'field_first_name');
  print l($a[0]['safe'],'user/'.$user->uid);

Your help is much appreciated!

berdir’s picture

You should be able to create a theme_username function (http://api.drupal.org/api/function/theme_username/6) for your theme and it should use that everywhere.

robby.smith’s picture

this seems very cool. with privatemsg 6.x-1.1 released, is there any update on this new feature?

faruq1256’s picture

Version: 6.x-1.x-dev » 5.x-3.0
Component: Code » User interface
Assigned: Unassigned » faruq1256
Category: feature » support
Priority: Normal » Critical

I am new to Drupal Please provide How can we change the privatemsg theme list like Gmail in Drupal5.20.I am trying from last 2 days.Please provide some links or Code.

Thank you in Advance.

naheemsays’s picture

The drupal 5 version of privatemsg is more or less unsupported. and Drupal 5 itself will probably become unsupported within a couple or three months.

your best bet is to migrate to Drupal 6 (or plan for drupal 7) especially if you are doing new development, which the new theming of messages suggests.

faruq1256’s picture

Thanking you for reply. But my project almost done.Its a tedious task now for me to migrate in to D6.If possible please provide CSS to change theme. Atleast i can show some what change. Anyways finally what i need is to slightly alter the message list with css

WaQuEe’s picture

Title: Theme privatemsg a la Gmail, add classes, etc » Wrong title page tile for embeded msg box
Version: 5.x-3.0 » 6.x-1.1
Assigned: faruq1256 » Unassigned
Status: Needs work » Active

I posted the issue in the wrong place....I appologise

berdir’s picture

Title: Wrong title page tile for embeded msg box » Theme privatemsg a la Gmail, add classes, etc
Version: 6.x-1.1 »
Category: support » feature
Priority: Critical » Normal
Status: Active » Needs work

Changing issue settings back to old values...

YK85’s picture

subscribing

fugazi’s picture

subscribing

okday’s picture

subscribe

dalad’s picture

subscribing

Relia’s picture

Hello i read the thread but i don't know where i have to write the code.

the first part in a custom module.

the second part: (#2. Customize the message listing output (phptemplate)) phptemplate what file exactly if is possible someone specifies the name of the file to change.

the third part in the module core, but what module core? In the core folder there are a lot modules.

the css I suppose in the privatemsg.css

Can someone help me???

berdir’s picture

You can't apply the existing, Privatemsg has changed a lot since this was proposed. This requires a rather big re-roll.

Witch’s picture

subscribe

mrgoltra’s picture

subsribing.

achikas’s picture

subscribe

jrivelli’s picture

Component: User interface » Code

So at this time there are no templates for privatemsg? It would be so sweet if there was at least another option besides the default view, Similar to gmail would be nice because it is widely used :)

wickedwookie’s picture

Version: » 6.x-2.x-dev

subscribe.. seems sensible that there should be some way to adapt the appearance

bkrall’s picture

Version: 6.x-2.x-dev » 7.x-1.0

This is awesome. Have you considered releasing this as a submodule to PrivateMsg?

ptmkenny’s picture

Version: 7.x-1.0 » 6.x-2.x-dev
Status: Needs work » Closed (won't fix)

This issue started off about 5.x version of Privatemsg, so the code examples are old and inaccurate. I'm closing this issue so that it doesn't lead people in the wrong direction. Feel free to start any questions about theming the 7.x version of Privatemsg as new issues.