View Issue Details

IDProjectCategoryView StatusLast Update
0007840mantisbtcustomizationpublic2016-11-10 04:08
ReporterstefanvandenoordAssigned To 
PrioritynormalSeverityfeatureReproducibilityN/A
Status acknowledgedResolutionopen 
Product Version 
Target VersionFixed in Version 
Summary0007840: Customizable 'my view' page
Description

I think it would be great if the 'my view' page was customizable. For example, the user preferences could include a checkbox for each standard 'my view' block, as well as each filter available to the user. The user could then also have the results of certain filters available on the 'my view' page, and could hide standard blocks that she doesn't need.

TagsNo tags attached.

Relationships

has duplicate 0007065 closeddregad Customize box layout on My View page 
has duplicate 0007025 closedgiallu Would like to create filters and have them visible from the My View page 
has duplicate 0013348 closedatrol Change the directory of closed bugs 
has duplicate 0013358 closedatrol Resolved items showing up in the Unassigned view 
has duplicate 0005048 closeddregad Sort My View by _____ 
has duplicate 0005832 closeddregad My View settings on a per-user basis 
has duplicate 0006412 closeddregad My View be created by custom filters. 
has duplicate 0014007 closedatrol Custom fileds in my_view_page 
has duplicate 0006480 closeddregad custom "My View" page for each user or access level 
has duplicate 0015741 closedatrol my_view_page.php cannot be customized 
related to 0021895 new Support saved filters in My View page 

Activities

vboctor

vboctor

2007-07-29 22:14

manager   ~0015284

I think it would be a good idea for users to add My View boxes based on filters that they have access to. Also to remove such boxes using some configuration page or using AJAX to close the windows. We may consider support for minimizing such windows.

2007-10-23 13:55

 

customMyView.diff (70,617 bytes)
? account_my_view_add.php
? account_my_view_delete.php
? account_my_view_page.php
? account_my_view_sequence.php
Index: config_defaults_inc.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/config_defaults_inc.php,v
retrieving revision 1.365
diff -u -r1.365 config_defaults_inc.php
--- config_defaults_inc.php	4 Oct 2007 05:59:04 -0000	1.365
+++ config_defaults_inc.php	23 Oct 2007 17:39:02 -0000
@@ -195,7 +195,7 @@

 	# the sender email, part of 'From: ' header in emails
  	$g_from_email			= 'noreply@example.com';
-
+
 	# the sender name, part of 'From: ' header in emails
 	$g_from_name			= 'Mantis Bug Tracker';

@@ -296,8 +296,8 @@
 	$g_phpMailer_method		= 0;

 	# This option allows you to use a remote SMTP host.  Must use the phpMailer script
-	# One or more hosts, separated by a semicolon, can be listed.
-	# You can also specify a different port for each host by using this
+	# One or more hosts, separated by a semicolon, can be listed.
+	# You can also specify a different port for each host by using this
 	# format: [hostname:port] (e.g. "smtp1.example.com:25;smtp2.example.com").
 	# Hosts will be tried in order.
 	$g_smtp_host			= 'localhost';
@@ -308,7 +308,7 @@
 	$g_smtp_username = '';
 	$g_smtp_password = '';

-	# It is recommended to use a cronjob or a scheduler task to send emails.
+	# It is recommended to use a cronjob or a scheduler task to send emails.
 	# The cronjob should typically run every 5 minutes.  If no cronjob is used,
 	# then user will have to wait for emails to be sent after performing an action
 	# which triggers notifications.  This slows user performance.
@@ -477,7 +477,7 @@
 	# resolution, fixed_in_version, view_state, os, os_build, platform, version, date_submitted, attachment,
 	# category, sponsorship_total, severity, status, last_updated, summary, bugnotes_count
 	$g_view_issues_page_columns = array ( 'selection', 'edit', 'priority', 'id', 'sponsorship_total', 'bugnotes_count', 'attachment', 'category', 'severity', 'status', 'last_updated', 'summary' );
-
+
 	# A configuration option that identifies the columns to be show on the print issues page.
 	# In Mantis 1.1, this option can be overriden using the Generic Configuration screen.
 	# This configuration can be overriden dynamically by overriding the custom function "get_columns_to_view".
@@ -519,12 +519,12 @@

 	# Show user avatar
 	# the current implementation is based on http://www.gravatar.com
-	# users will need to register there the same address used in
+	# users will need to register there the same address used in
 	# this mantis installation to have their avatar shown
 	# Please note: upon registration or avatar change, it takes some time for
 	# the updated gravatar images to show on sites
 	$g_show_avatar = OFF;
-
+
 	# Only users above this threshold will have their avatar shown
 	$g_show_avatar_threshold = DEVELOPER;

@@ -560,11 +560,11 @@

 	# how many graphs to put in each row in the advanced summary page
 	$g_graph_summary_graphs_per_row = 2;
-
+
 	# initial graph type selected on bug_graph_page (see that page for possible values)
 	# 0 asks user to select
 	$g_default_graph_type = 0;
-
+
 	# graph colours, once the list is exhausted it will repeat
 	$g_graph_colors = array('coral', 'red', 'blue', 'black', 'green', 'orange', 'pink', 'brown', 'gray',
 	        'blueviolet','chartreuse','fuschia','indigo');
@@ -646,7 +646,7 @@

 	# Default bug priority when reporting a new bug
 	$g_default_bug_priority = NORMAL;
-
+
 	# Default bug reproducibility when reporting a new bug
 	$g_default_bug_reproducibility = REPRODUCIBILITY_HAVENOTTRIED;

@@ -793,7 +793,7 @@
 	# DISK, DATABASE, or FTP.
 	$g_file_upload_method	= DATABASE;

-	# When using FTP or DISK for storing uploaded files, this setting control
+	# When using FTP or DISK for storing uploaded files, this setting control
 	# the access permissions they will have on the web server: with the default
 	# value (0400) files will be read-only, and accessible only by the user
 	# running the apache process (probably "apache" in Linux and "Administrator"
@@ -877,7 +877,7 @@
 	$g_ldap_bind_dn			= '';
 	$g_ldap_bind_passwd		= '';
 	$g_use_ldap_email		= OFF; # Should we send to the LDAP email address or what MySql tells us
-
+
 	# The LDAP Protocol Version, if 0, then the protocol version is not set.
 	$g_ldap_protocol_version = 0;

@@ -1114,10 +1114,10 @@

 	# threshold for viewing roadmap
 	$g_roadmap_view_threshold = VIEWER;
-
+
 	# threshold for updating roadmap, target_version, etc
 	$g_roadmap_update_threshold = DEVELOPER;
-
+
 	# status change thresholds
 	$g_update_bug_status_threshold = DEVELOPER;

@@ -1126,7 +1126,7 @@

 	# access level needed to set a bug sticky
 	$g_set_bug_sticky_threshold			= MANAGER;
-
+
 	# The minimum access level for someone to be a member of the development team
 	# and appear on the project information page.
 	$g_development_team_threshold = DEVELOPER;
@@ -1314,7 +1314,7 @@
 	# Rather than launching a separate page, the filters are updated in-line in the
 	# view_all_bugs_page.
 	$g_dhtml_filters = ON;
-
+
 	# The service to use to create a short URL.  The %s will be replaced by the long URL.
 	$g_create_short_url = 'http://tinyurl.com/create.php?url=%s';

@@ -1352,6 +1352,7 @@
 	$g_mantis_custom_field_string_table     = '%db_table_prefix%_custom_field_string%db_table_suffix%';
 	$g_mantis_upgrade_table					= '%db_table_prefix%_upgrade%db_table_suffix%';
 	$g_mantis_filters_table					= '%db_table_prefix%_filters%db_table_suffix%';
+	$g_mantis_filters_my_view_table			= '%db_table_prefix%_filters_my_view%db_table_suffix%';
 	$g_mantis_sponsorship_table				= '%db_table_prefix%_sponsorship%db_table_suffix%';
 	$g_mantis_tokens_table					= '%db_table_prefix%_tokens%db_table_suffix%';
 	$g_mantis_project_hierarchy_table		= '%db_table_prefix%_project_hierarchy%db_table_suffix%';
@@ -1493,7 +1494,7 @@
 	# WARNING: Potential security hazard.  Only turn this on when you really
 	# need it (for debugging/profiling)
 	$g_show_queries_list	= OFF;
-
+
 	# --- detailed error messages -----
 	# Shows a list of variables and their values when an error is triggered
 	# Only applies to error types configured to 'halt' in $g_display_errors, below
@@ -1581,7 +1582,7 @@
 	# Note:
 	# - Extensions must be in lower case
 	# - All icons will be displayed as 16x16 pixels.
-	$g_file_type_icons = array(
+	$g_file_type_icons = array(
 		'7z'	=> 'zip.gif',
 		'ace'	=> 'zip.gif',
 		'arj'	=> 'zip.gif',
@@ -1675,19 +1676,37 @@
 	# Number of bugs shown in each box
 	$g_my_view_bug_count = 10;

-	# Boxes to be shown and their order
-	# A box that is not to be shown can have its value set to 0
+	# Boxes to be shown in "My View". Put them in the order you want them to appear
 	$g_my_view_boxes = array (
-		'assigned'      => '1',
-		'unassigned'    => '2',
-		'reported'      => '3',
-		'resolved'      => '4',
-		'recent_mod'	=> '5',
-		'monitored'		=> '6',
-		'feedback'		=> '0',
-		'verify'		=> '0'
+		FILTER_ASSIGNED,
+		FILTER_UNASSIGNED,
+		FILTER_REPORTED,
+		FILTER_RESOLVED,
+		FILTER_RECENT_MOD,
+		FILTER_MONITORED,
+		// FILTER_FEEDBACK,
+		// FILTER_VERIFY,
+	);
+
+	# Allows you to set a custom "My View" on an access level basis
+	# To do this, set the key of the first dimension to the access level, then
+	# make the value an array of filters. For example:
+	# $g_my_view_access_boxes = array (
+	# 	ADMINISTRATOR => array(
+	#		FILTER_UNASSIGNED,
+	#		FILTER_ASSIGNED
+	#	),
+	#   REPORTER => array(
+	#		FILTER_REPORTED,
+	#		FILTER_MONITORED
+	#	)
+	# );
+	$g_my_view_access_boxes = array (
 	);

+	# threshold needed to customize the 'My View' screen
+	$g_custom_my_view_threshold = ANYBODY;
+
 	# Toggle whether 'My View' boxes are shown in a fixed position (i.e. adjacent boxes start at the same vertical position)
 	$g_my_view_boxes_fixed_position = ON;

@@ -1703,7 +1722,7 @@
 	$g_rss_enabled = ON;

 	# This seed is used as part of the inputs for calculating the authentication key for the RSS feeds.
-	# If this seed changes, all the existing keys for the RSS feeds will become invalid.  This is
+	# If this seed changes, all the existing keys for the RSS feeds will become invalid.  This is
 	# defaulted to the database user name, but it is recommended to overwrite it with a specific value
 	# on installation.
 	$g_rss_key_seed = '%db_username%';
@@ -1782,7 +1801,7 @@
 	# Custom Group Actions
 	#
 	# This extensibility model allows developing new group custom actions.  This
-	# can be implemented with a totally custom form and action pages or with a
+	# can be implemented with a totally custom form and action pages or with a
 	# pre-implemented form and action page and call-outs to some functions.  These
 	# functions are to be implemented in a predefined file whose name is based on
 	# the action name.  For example, for an action to add a note, the action would
@@ -1810,26 +1829,26 @@
 	#####################
 	# Wiki Integration
 	#####################
-
+
 	# Wiki Integration Enabled?
 	$g_wiki_enable = OFF;

 	# Wiki Engine (supported engines: 'dokuwiki', 'mediawiki', 'xwiki')
 	$g_wiki_engine = 'dokuwiki';
-
+
 	# Wiki namespace to be used as root for all pages relating to this mantis installation.
 	$g_wiki_root_namespace = 'mantis';
-
+
 	# URL under which the wiki engine is hosted.  Must be on the same server.
 	$g_wiki_engine_url = $t_protocol . '://' . $t_host . '/%wiki_engine%/';
-
+
 	#####################
 	# Recently Visited
 	#####################

 	# Whether to show the most recently visited issues or not.  At the moment we always track them even if this flag is off.
 	$g_recently_visited = ON;
-
+
 	# The maximum number of issues to keep in the recently visited list.
 	$g_recently_visited_count = 5;

@@ -1893,7 +1912,7 @@
 	# Threshold needed to be able to create and modify global profiles
 	$g_manage_global_profile_threshold = MANAGER;

-	# Allows the users to enter free text when reporting/updating issues
+	# Allows the users to enter free text when reporting/updating issues
 	# for the profile related fields (i.e. platform, os, os build)
 	$g_allow_freetext_in_profile_fields = ON;

@@ -1907,7 +1926,7 @@

 	# The twitter account user name.
 	$g_twitter_username = '';
-
+
 	# The twitter account password.
 	$g_twitter_password = '';
 ?>
Index: my_view_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/my_view_page.php,v
retrieving revision 1.17
diff -u -r1.17 my_view_page.php
--- my_view_page.php	28 Jul 2007 10:15:15 -0000	1.17
+++ my_view_page.php	23 Oct 2007 17:39:02 -0000
@@ -17,6 +17,7 @@
 	require_once( $t_core_path . 'compress_api.php' );
 	require_once( $t_core_path . 'filter_api.php' );
 	require_once( $t_core_path . 'last_visited_api.php' );
+	require_once( $t_core_path . 'icon_api.php' );

 	auth_ensure_user_authenticated();

@@ -31,7 +32,7 @@
 	}

 	html_page_top2();
-
+
 	print_recently_visited();

 	$f_page_number		= gpc_get_int( 'page_number', 1 );
@@ -40,11 +41,6 @@
 	$t_bug_count = null;
 	$t_page_count = null;

-	$t_boxes = config_get( 'my_view_boxes' );
-	asort ($t_boxes);
-	reset ($t_boxes);
-	#print_r ($t_boxes);
-
 	$t_project_id = helper_get_current_project();
 ?>

@@ -61,91 +57,125 @@
 		echo '</td>';
 		echo '</tr>';
 	}
-?>

-<?php
-	$t_number_of_boxes = count ( $t_boxes );
 	$t_boxes_position = config_get( 'my_view_boxes_fixed_position' );
+
+	$t_custom_my_view_threshold = config_get('custom_my_view_threshold');
+
+	# Make sure they have access to define a custom 'my view'
+	if (access_has_global_level($t_custom_my_view_threshold)) {
+
+		# Get the list of custom my_view filters
+		$t_filters = filter_db_get_my_view( $t_current_user_id, TRUE );
+
+		# If they set no custom filters, then get the default view
+		if (count($t_filters) <= 0)
+			$t_filters = filter_get_default_my_view( $t_project_id );
+
+	}
+	else {
+		$t_filters = filter_get_default_my_view( $t_project_id );
+	}
+
+
+	$t_number_of_boxes = count($t_filters);
+
 	$t_counter = 0;

-	while (list ($t_box_title, $t_box_display) = each ($t_boxes)) {
-		# don't display bugs that are set as 0
-		if ($t_box_display == 0) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+	foreach ($t_filters AS $filter) {

-		# don't display "Assigned to Me" bugs to users that bugs can't be assigned to
-		else if ( $t_box_title == 'assigned' && ( current_user_is_anonymous() OR user_get_assigned_open_bug_count( $t_current_user_id, $t_project_id ) == 0 ) ) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+		$t_counter++;

-		# don't display "Monitored by Me" bugs to users that can't monitor bugs
-		else if ( $t_box_title == 'monitored' && ( current_user_is_anonymous() OR !access_has_project_level( config_get( 'monitor_bug_threshold' ), $t_project_id, $t_current_user_id ) ) ) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+		# If the filter is for a specific project, only use that project
+		if (array_key_exists('project_id', $filter) && $filter['project_id'] != 0)
+			$t_filter_project_id = $filter['project_id'];
+		else
+			$t_filter_project_id = $t_project_id;
+
+		if ( ON == $t_boxes_position ) {
+
+			# for even box number start new row and column
+			if ( 1 == $t_counter % 2 ) {
+				echo '<tr><td valign="top" width="50%">';
+
+				print_filter_my_view_box(
+						$filter['name'],
+						$f_page_number,
+						$t_per_page,
+						$filter['filter'],
+						$t_filter_project_id,
+						$t_current_user_id,
+						null,
+						array_key_exists('url', $filter)?"view_all_set.php?type=1&amp;temporary=y&amp;". $filter['url']:null
+					);

-		# don't display "Reported by Me" bugs to users that can't report bugs
-		else if ( in_array( $t_box_title, array( 'reported', 'feedback', 'verify' ) ) &&
-				( current_user_is_anonymous() OR !access_has_project_level( config_get( 'report_bug_threshold' ), $t_project_id, $t_current_user_id ) ) ) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+				echo '</td>';
+			}

-		# display the box
+			# for odd box number only start new column
+			elseif ( 0 == $t_counter%2 ) {
+				echo '<td valign="top" width="50%">';
+
+				print_filter_my_view_box(
+						$filter['name'],
+						$f_page_number,
+						$t_per_page,
+						$filter['filter'],
+						$t_filter_project_id,
+						$t_current_user_id,
+						null,
+						array_key_exists('url', $filter)?"view_all_set.php?type=1&amp;temporary=y&amp;". $filter['url']:null
+					);
+
+				echo '</td></tr>';
+			}
+
+			# for odd number of box display one empty table cell in second column
+			if ( ( $t_counter == $t_number_of_boxes ) && 1 == $t_counter%2 ) {
+				echo '<td valign="top" width="50%"></td></tr>';
+			}
+
+		}
 		else {
-			$t_counter++;

-			# check the style of displaying boxes - fixed (ie. each box in a separate table cell) or not
-			if ( ON == $t_boxes_position ) {
-				# for even box number start new row and column
-				if ( 1 == $t_counter%2 ) {
-					echo '<tr><td valign="top" width="50%">';
-					include( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'my_view_inc.php' );
-					echo '</td>';
-				}
-
-				# for odd box number only start new column
-				elseif ( 0 == $t_counter%2 ) {
-					echo '<td valign="top" width="50%">';
-					include( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'my_view_inc.php' );
-					echo '</td></tr>';
-				}
-
-				# for odd number of box display one empty table cell in second column
-				if ( ( $t_counter == $t_number_of_boxes ) && 1 == $t_counter%2 ) {
-					echo '<td valign="top" width="50%"></td></tr>';
-				}
-			}
-			else if ( OFF == $t_boxes_position ) {
-				# start new table row and column for first box
-				if ( 1 == $t_counter ) {
-					echo '<tr><td valign="top" width="50%">';
-				}
-
-				# start new table column for the second half of boxes
-				if ( $t_counter == ceil ($t_number_of_boxes/2) + 1 ) {
-					echo '<td valign="top" width="50%">';
-				}
-
-				# display the required box
-				include( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'my_view_inc.php' );
-				echo '<br />';
-
-				# close the first column for first half of boxes
-				if ( $t_counter == ceil ($t_number_of_boxes/2) ) {
-					echo '</td>';
-				}
-
-				# close the table row after all of the boxes
-				if ( $t_counter == $t_number_of_boxes ) {
-					echo '</td></tr>';
-				}
+			# start new table row and column for first box
+			if ( 1 == $t_counter ) {
+				echo '<tr><td valign="top" width="50%">';
+			}
+
+			# start new table column for the second half of boxes
+			if ( $t_counter == ceil ($t_number_of_boxes/2) + 1 ) {
+				echo '<td valign="top" width="50%">';
+			}
+
+			# display the required box
+
+			print_filter_my_view_box(
+					$filter['name'],
+					$f_page_number,
+					$t_per_page,
+					$filter['filter'],
+					$t_filter_project_id,
+					$t_current_user_id,
+					null,
+					array_key_exists('url', $filter)?"view_all_set.php?type=1&amp;temporary=y&amp;". $filter['url']:null
+				);
+
+			echo '<br />';
+
+			# close the first column for first half of boxes
+			if ( $t_counter == ceil ($t_number_of_boxes/2) ) {
+				echo '</td>';
+			}
+
+			# close the table row after all of the boxes
+			if ( $t_counter == $t_number_of_boxes ) {
+				echo '</td></tr>';
 			}
 		}
-	}

-?>
+	}

-<?php
 	if ( $t_status_legend_position == STATUS_LEGEND_POSITION_BOTTOM || $t_status_legend_position == STATUS_LEGEND_POSITION_BOTH ) {
 		echo '<tr>';
 		echo '<td colspan="2">';
@@ -160,4 +190,4 @@

 <?php
 	html_page_bottom1( __FILE__ );
-?>
+?>
\ No newline at end of file
Index: core/constant_inc.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/constant_inc.php,v
retrieving revision 1.74
diff -u -r1.74 constant_inc.php
--- core/constant_inc.php	24 Sep 2007 19:24:30 -0000	1.74
+++ core/constant_inc.php	23 Oct 2007 17:39:03 -0000
@@ -261,7 +261,7 @@
 	define( 'ERROR_LDAP_UPDATE_FAILED',				1402 );
 	define( 'ERROR_LDAP_USER_NOT_FOUND',			1403 );
 	define( 'ERROR_LDAP_EXTENSION_NOT_LOADED',		1404 );
-
+
 	# ERROR_CATEGORY_*
 	define( 'ERROR_CATEGORY_DUPLICATE',				1500 );
 	define( 'ERROR_CATEGORY_NO_ACTION',				1501 );
@@ -296,7 +296,7 @@
 	# ERROR_FILTER_*
 	define( 'ERROR_FILTER_NOT_FOUND', 2000 );
 	define( 'ERROR_FILTER_TOO_OLD', 2001 );
-
+
 	# ERROR_TWITTER_*
 	define( 'ERROR_TWITTER_NO_CURL_EXT', 2100 );

@@ -321,6 +321,16 @@
 	define( 'FILTER_POSITION_BOTTOM',			2 );
 	define( 'FILTER_POSITION_BOTH',				3 );  // FILTER_POSITION_TOP | FILTER_POSITION_BOTTOM (bitwise OR)

+	    # Default Filters
+	define( 'FILTER_ASSIGNED',					-1 );
+	define( 'FILTER_RECENT_MOD',				-2 );
+	define( 'FILTER_REPORTED',					-3 );
+	define( 'FILTER_RESOLVED',					-4 );
+	define( 'FILTER_UNASSIGNED',				-5 );
+	define( 'FILTER_MONITORED',					-6 );
+	define( 'FILTER_FEEDBACK',					-7 );
+	define( 'FILTER_VERIFY',					-8 );
+
 	# Flags for settings E-mail categories
 	define( 'EMAIL_CATEGORY_PROJECT_CATEGORY',	1);

Index: core/filter_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/filter_api.php,v
retrieving revision 1.164
diff -u -r1.164 filter_api.php
--- core/filter_api.php	19 Oct 2007 06:13:00 -0000	1.164
+++ core/filter_api.php	23 Oct 2007 17:39:03 -0000
@@ -120,7 +120,7 @@
 			if ( is_string( $p_field_value ) && is_blank( $p_field_value ) ) {
 				return true;
 			}
-
+
 			if ( is_bool( $p_field_value ) && !$p_field_value ) {
 				return true;
 			}
@@ -138,7 +138,7 @@
 	# $p_field_name - The field name.
 	# $p_field_value - The field value (can be an array)
 	function filter_encode_field_and_value( $p_field_name, $p_field_value ) {
-		$t_query_array = array();
+		$t_query_array = array();
 		if ( is_array( $p_field_value ) ) {
 			$t_count = count( $p_field_value );
 			if ( $t_count > 1 ) {
@@ -158,7 +158,7 @@
 	# Get a permalink for the current active filter.  The results of using these fields by other users
 	# can be inconsistent with the original results due to fields like "Myself", "Current Project",
 	# and due to access level.
-	# Returns the search.php?xxxx or an empty string if no criteria applied.
+	# Returns the search.php?xxxx or an empty string if no criteria applied.
 	function filter_get_url( $p_custom_filter ) {
 		$t_query = array();

@@ -267,26 +267,26 @@
 			if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_DAY] ) ) {
 				$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_START_DAY, $p_custom_filter[FILTER_PROPERTY_START_DAY] );
 			}
-
+
 			if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_DAY] ) ) {
 				$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_END_DAY, $p_custom_filter[FILTER_PROPERTY_END_DAY] );
 			}
-
+
 			if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_MONTH] ) ) {
 				$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_START_MONTH, $p_custom_filter[FILTER_PROPERTY_START_MONTH] );
 			}
-
+
 			if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_MONTH] ) ) {
 				$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_END_MONTH, $p_custom_filter[FILTER_PROPERTY_END_MONTH] );
 			}
-
+
 			if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_YEAR] ) ) {
 				$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_START_YEAR, $p_custom_filter[FILTER_PROPERTY_START_YEAR] );
 			}
-
+
 			if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_YEAR] ) ) {
 				$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_END_YEAR, $p_custom_filter[FILTER_PROPERTY_END_YEAR] );
-			}
+			}
 		}

 		if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] ) ) {
@@ -426,6 +426,7 @@
 			$t_project_id	= $p_project_id;
 		}

+
 		if ( $p_custom_filter === null ) {
 			# Prefer current_user_get_bug_filter() over user_get_filter() when applicable since it supports
 			# cookies set by previous version of the code.
@@ -476,7 +477,7 @@
 		$t_all_projects_found = false;
 		$t_new_project_ids = array();
 		foreach ( $t_project_ids as $t_pid ) {
-			if ( $t_pid == META_FILTER_CURRENT ) {
+			if ( $t_pid == META_FILTER_CURRENT ) {
 				$t_pid = $t_project_id;
 			}

@@ -505,7 +506,7 @@
 		} else {
 			$t_project_ids = $t_new_project_ids;
 		}
-
+
 		if ( $t_projects_query_required ) {
 			// expand project ids to include sub-projects
 			if ( $t_include_sub_projects ) {
@@ -566,7 +567,7 @@
 			}

 			// both queries can't be null, so we either have one of them or both.
-
+
 			if ( $t_private_and_public_query === null ) {
 				$t_project_query = $t_public_only_query;
 			} else if ( $t_public_only_query === null ) {
@@ -617,7 +618,7 @@
 					}
 				}
 			}
-
+
 			if ( 1 < count( $t_clauses ) ) {
 				$t_reporter_query = "( $t_bug_table.reporter_id in (". implode( ', ', $t_clauses ) .") )";
 			} else {
@@ -666,7 +667,7 @@
 					}
 				}
 			}
-
+
 			if ( 1 < count( $t_clauses ) ) {
 				$t_handler_query = "( $t_bug_table.handler_id in (". implode( ', ', $t_clauses ) .") )";
 			} else {
@@ -1011,7 +1012,7 @@
 					array_push( $t_clauses, "'$c_target_version'" );
 				}
 			}
-
+
 			#echo var_dump( $t_clauses ); exit;
 			if ( 1 < count( $t_clauses ) ) {
 				array_push( $t_where_clauses, "( $t_bug_table.target_version in (". implode( ', ', $t_clauses ) .") )" );
@@ -1066,7 +1067,7 @@
 			array_push( $t_join_clauses, "LEFT JOIN $t_bug_relationship_table $t_table_name ON $t_table_name.destination_bug_id = $t_bug_table.id" );
 			array_push( $t_join_clauses, "LEFT JOIN $t_bug_relationship_table ${t_table_name}2 ON ${t_table_name}2.source_bug_id = $t_bug_table.id" );
 			// get reverse relationships
- 			array_push( $t_clauses, "($t_table_name.relationship_type='$t_comp_type' AND $t_table_name.source_bug_id='$c_rel_bug')" );
+			array_push( $t_clauses, "($t_table_name.relationship_type='$t_comp_type' AND $t_table_name.source_bug_id='$c_rel_bug')" );
 			array_push( $t_clauses, "($t_table_name"."2.relationship_type='$c_rel_type' AND $t_table_name"."2.destination_bug_id='$c_rel_bug')" );
 			array_push( $t_where_clauses, '('. implode( ' OR ', $t_clauses ) .')' );
 		}
@@ -1081,7 +1082,7 @@
 				$t_tags_all = array();
 				$t_tags_any = array();
 				$t_tags_none = array();
-
+
 				foreach( $t_tags as $t_tag_row ) {
 					switch ( $t_tag_row['filter'] ) {
 						case 1:
@@ -1095,13 +1096,13 @@
 							break;
 					}
 				}
-
+
 				if ( 0 < $t_filter['tag_select'] && tag_exists( $t_filter['tag_select'] ) ) {
 					$t_tags_any[] = tag_get( $t_filter['tag_select'] );
 				}
-
+
 				$t_bug_tag_table = config_get( 'mantis_bug_tag_table' );
-
+
 				if ( count( $t_tags_all ) ) {
 					$t_clauses = array();
 					foreach ( $t_tags_all as $t_tag_row ) {
@@ -1109,7 +1110,7 @@
 					}
 					array_push( $t_where_clauses, '('. implode( ' AND ', $t_clauses ) .')' );
 				}
-
+
 				if ( count( $t_tags_any ) ) {
 					$t_clauses = array();
 					foreach ( $t_tags_any as $t_tag_row ) {
@@ -1117,16 +1118,16 @@
 					}
 					array_push( $t_where_clauses, "$t_bug_table.id IN ( SELECT bug_id FROM $t_bug_tag_table WHERE ( ". implode( ' OR ', $t_clauses ) .') )' );
 				}
-
+
 				if ( count( $t_tags_none ) ) {
 					$t_clauses = array();
 					foreach ( $t_tags_none as $t_tag_row ) {
 						array_push( $t_clauses, "$t_bug_tag_table.tag_id = $t_tag_row[id]" );
 					}
 					array_push( $t_where_clauses, "$t_bug_table.id NOT IN ( SELECT bug_id FROM $t_bug_tag_table WHERE ( ". implode( ' OR ', $t_clauses ) .') )' );
-				}
+				}

-			}
+			}
 		}

 		# custom field filters
@@ -1152,10 +1153,10 @@
 				if ( !$t_any_found ) {
 					$t_def = custom_field_get_definition( $t_cfid );
 					$t_table_name = $t_custom_field_string_table . '_' . $t_cfid;
-                    # We need to filter each joined table or the result query will explode in dimensions
-                    # Each custom field will result in a exponential growth like Number_of_Issues^Number_of_Custom_Fields
-                    # and only after this process ends (if it is able to) the result query will be filtered
-                    # by the WHERE clause and by the DISTINCT clause
+					# We need to filter each joined table or the result query will explode in dimensions
+					# Each custom field will result in a exponential growth like Number_of_Issues^Number_of_Custom_Fields
+					# and only after this process ends (if it is able to) the result query will be filtered
+					# by the WHERE clause and by the DISTINCT clause
 					$t_cf_join_clause = "LEFT JOIN $t_custom_field_string_table $t_table_name ON $t_table_name.bug_id = $t_bug_table.id AND $t_table_name.field_id = $t_cfid ";

 					if ($t_def['type'] == CUSTOM_FIELD_TYPE_DATE) {
@@ -1186,7 +1187,7 @@
 						$t_filter_array = array();
 						foreach( $t_filter['custom_fields'][$t_cfid] as $t_filter_member ) {
 							$t_filter_member = stripslashes( $t_filter_member );
-							if ( META_FILTER_NONE == $t_filter_member ) {
+							if ( META_FILTER_NONE == $t_filter_member ) {
 								# coerce filter value if selecting META_FILTER_NONE so it will match empty fields
 								$t_filter_member = '';
 								# but also add those _not_ present in the custom field string table
@@ -1218,7 +1219,7 @@
 			$c_search = db_prepare_string( $t_filter['search'] );
 			$c_search_int = db_prepare_int( $t_filter['search'] );
 			$t_textsearch_where_clause = '(' . db_helper_like( 'summary', "%$c_search%" ) .
-							 ' OR ' . db_helper_like( "$t_bug_text_table.description", "%$c_search%" ) .
+							 ' OR ' . db_helper_like( "$t_bug_text_table.description", "%$c_search%" ) .
 							 ' OR ' . db_helper_like( "$t_bug_text_table.steps_to_reproduce", "%$c_search%" ) .
 							 ' OR ' . db_helper_like( "$t_bug_text_table.additional_information", "%$c_search%" ) .
 							 " OR ( $t_bug_table.id = '$c_search_int' ) )";
@@ -1346,21 +1347,21 @@
 		if ( ( 'on' == $t_filter['sticky_issues'] ) && ( NULL !== $p_show_sticky ) ) {
 			$t_order_array[] = "sticky DESC";
 		}
-
+
 		$t_join = '';
 		for ( $i=0; $i < count( $t_sort_fields ); $i++ ) {
 			$c_sort = db_prepare_string( $t_sort_fields[$i] );

 			if ( ! in_array( $t_sort_fields[$i], array_slice( $t_sort_fields, $i + 1) ) ) {

-        		# if sorting by a custom field
-        		if ( strpos( $c_sort, 'custom_' ) === 0 ) {
-	        		$t_custom_field = substr( $c_sort, strlen( 'custom_' ) );
-        			$t_custom_field_id = custom_field_get_id_from_name( $t_custom_field );
-    	    		$t_join .= " LEFT JOIN $t_custom_field_string_table ON ( ( $t_custom_field_string_table.bug_id = $t_bug_table.id ) AND ( $t_custom_field_string_table.field_id = $t_custom_field_id ) )";
-        			$c_sort = "$t_custom_field_string_table.value";
-        			$t_select_clauses[] = "$t_custom_field_string_table.value";
-     		   	}
+				# if sorting by a custom field
+				if ( strpos( $c_sort, 'custom_' ) === 0 ) {
+					$t_custom_field = substr( $c_sort, strlen( 'custom_' ) );
+					$t_custom_field_id = custom_field_get_id_from_name( $t_custom_field );
+					$t_join .= " LEFT JOIN $t_custom_field_string_table ON ( ( $t_custom_field_string_table.bug_id = $t_bug_table.id ) AND ( $t_custom_field_string_table.field_id = $t_custom_field_id ) )";
+					$c_sort = "$t_custom_field_string_table.value";
+					$t_select_clauses[] = "$t_custom_field_string_table.value";
+				}

 				if ( 'DESC' == $t_dir_fields[$i] ) {
 					$c_dir = 'DESC';
@@ -1375,10 +1376,10 @@
 		# add basic sorting if necessary
 		if ( ! in_array( 'last_updated', $t_sort_fields ) ) {
 			$t_order_array[] = 'last_updated DESC';
-        }
+		}
 		if ( ! in_array( 'date_submitted', $t_sort_fields ) ) {
 			$t_order_array[] = 'date_submitted DESC';
-        }
+		}

 		$t_order = " ORDER BY " . implode( ', ', $t_order_array );
 		$t_select	= implode( ', ', array_unique( $t_select_clauses ) );
@@ -1405,24 +1406,24 @@
 		$row_count = db_num_rows( $result2 );

 		$t_id_array_lastmod = array();
-
+
 		for ( $i=0 ; $i < $row_count ; $i++ ) {
 			$row = db_fetch_array( $result2 );
 			$t_id_array_lastmod[] = db_prepare_int ( $row['id'] );
-
+
 			$row['date_submitted'] = db_unixtimestamp ( $row['date_submitted'] );
 			$row['last_updated'] = db_unixtimestamp ( $row['last_updated'] );
-
+
 			array_push( $rows, $row );
 		}

 		$t_id_array_lastmod = array_unique( $t_id_array_lastmod );
-
+
 		// paulr: it should be impossible for t_id_array_lastmod to be array():
 		// that would imply that $t_id_array is null which aborts this function early
 		//if ( count( $t_id_array_lastmod ) > 0 ) {
 		$t_where = "WHERE $t_bugnote_table.bug_id in (" . implode( ", ", $t_id_array_lastmod ) . ")";
-
+
 		$query3 = "SELECT DISTINCT bug_id,MAX(last_modified) as last_modified, COUNT(last_modified) as count FROM $t_bugnote_table $t_where GROUP BY bug_id";

 		# perform query
@@ -1432,7 +1433,7 @@

 		for ( $i=0 ; $i < $row_count ; $i++ ) {
 			$row = db_fetch_array( $result3 );
-
+
 			$t_stats[ $row['bug_id'] ] = $row;
 		}

@@ -1608,9 +1609,9 @@
 					|| ( ( AUTO == config_get( 'show_product_version' ) )
 								&& ( count( version_get_all_rows_with_subs( $t_project_id ) ) > 0 ) );
 			# overload handler_id setting if user isn't supposed to see them (ref #6189)
-			if ( ! access_has_project_level( config_get( 'view_handler_threshold' ), $t_project_id ) ) {
-				$t_filter['handler_id'] = array( META_FILTER_ANY );
-			}
+			if ( ! access_has_project_level( config_get( 'view_handler_threshold' ), $t_project_id ) ) {
+				$t_filter['handler_id'] = array( META_FILTER_ANY );
+			}
 		?>

 		<tr <?php PRINT "class=\"" . $t_trclass . "\""; ?>>
@@ -1776,7 +1777,7 @@
 										<input type="hidden" name="show_category[]" value="<?php echo string_display( $t_current );?>" />
 										<?php
 										$t_this_string = '';
-										if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
+										if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
 												|| ( is_blank( $t_current ) ) ) {
 											$t_any_found = true;
 										} else {
@@ -2028,7 +2029,7 @@
 										<input type="hidden" name="show_build[]" value="<?php echo string_display( $t_current );?>" />
 										<?php
 										$t_this_string = '';
-										if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
+										if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
 												|| ( is_blank( $t_current ) ) ) {
 											$t_any_found = true;
 										} else if ( META_FILTER_NONE == $t_current ) {
@@ -2066,7 +2067,7 @@
 										<input type="hidden" name="show_version[]" value="<?php echo string_display( $t_current );?>" />
 										<?php
 										$t_this_string = '';
-										if ( ( ( $t_current == META_FILTER_ANY ) && (is_numeric( $t_current ) ) )
+										if ( ( ( $t_current == META_FILTER_ANY ) && (is_numeric( $t_current ) ) )
 												|| ( is_blank( $t_current ) ) ) {
 											$t_any_found = true;
 										} else if ( META_FILTER_NONE == $t_current ) {
@@ -2103,7 +2104,7 @@
 										<input type="hidden" name="fixed_in_version[]" value="<?php echo string_display( $t_current );?>" />
 										<?php
 										$t_this_string = '';
-										if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
+										if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
 												|| ( is_blank( $t_current ) ) ) {
 											$t_any_found = true;
 										} else if ( META_FILTER_NONE == $t_current ) {
@@ -2135,38 +2136,38 @@
 			</td>
 			<?php } ?>
 			<td colspan="1" class="small-caption" valign="top" id="show_priority_filter_target">
-              <?php
+			  <?php
 							  $t_output = '';
-                $t_any_found = false;
-                if ( count( $t_filter['show_priority'] ) == 0 ) {
-                	PRINT lang_get( 'any' );
-                } else {
-                  $t_first_flag = true;
-                  foreach( $t_filter['show_priority'] as $t_current ) {
+				$t_any_found = false;
+				if ( count( $t_filter['show_priority'] ) == 0 ) {
+					PRINT lang_get( 'any' );
+				} else {
+				  $t_first_flag = true;
+				  foreach( $t_filter['show_priority'] as $t_current ) {
 										?>
 										<input type="hidden" name="show_priority[]" value="<?php echo $t_current;?>" />
 										<?php
-                  	$t_this_string = '';
+					$t_this_string = '';
 										if ( ( $t_current === META_FILTER_ANY ) || ( is_blank( $t_current ) ) || ( $t_current === 0 ) ) {
-                  		$t_any_found = true;
-	                  } else {
-	                  	$t_this_string = get_enum_element( 'priority', $t_current );
-	                  }
-	                  if ( $t_first_flag != true ) {
-	                  	$t_output = $t_output . '<br />';
-	                  } else {
-	                  	$t_first_flag = false;
-	                  }
-	                  $t_output = $t_output . $t_this_string;
-	                }
-	                if ( true == $t_any_found ) {
-	                 	PRINT lang_get( 'any' );
-	                } else {
-	                	PRINT $t_output;
-	                }
-	               }
-	              ?>
-	    	</td>
+						$t_any_found = true;
+					  } else {
+						$t_this_string = get_enum_element( 'priority', $t_current );
+					  }
+					  if ( $t_first_flag != true ) {
+						$t_output = $t_output . '<br />';
+					  } else {
+						$t_first_flag = false;
+					  }
+					  $t_output = $t_output . $t_this_string;
+					}
+					if ( true == $t_any_found ) {
+						PRINT lang_get( 'any' );
+					} else {
+						PRINT $t_output;
+					}
+				   }
+				  ?>
+			</td>
 			<td colspan="1" class="small-caption" valign="top" id="show_target_version_filter_target">
 							<?php
 								$t_output = '';
@@ -2181,7 +2182,7 @@
 										<input type="hidden" name="target_version[]" value="<?php echo string_display( $t_current );?>" />
 										<?php
 										$t_this_string = '';
-										if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
+										if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
 												|| ( is_blank( $t_current ) ) ) {
 											$t_any_found = true;
 										} else if ( META_FILTER_NONE == $t_current ) {
@@ -2269,7 +2270,7 @@
 		<script type="text/javascript" language="JavaScript">
 		<!--
 			function SwitchDateFields() {
-		    	// All fields need to be enabled to go back to the script
+				// All fields need to be enabled to go back to the script
 				document.filters_open.start_month.disabled = ! document.filters_open.do_filter_by_date.checked;
 				document.filters_open.start_day.disabled = ! document.filters_open.do_filter_by_date.checked;
 				document.filters_open.start_year.disabled = ! document.filters_open.do_filter_by_date.checked;
@@ -2277,7 +2278,7 @@
 				document.filters_open.end_day.disabled = ! document.filters_open.do_filter_by_date.checked;
 				document.filters_open.end_year.disabled = ! document.filters_open.do_filter_by_date.checked;

-		   		return true;
+				return true;
 			}
 		// -->
 		</script>
@@ -2342,7 +2343,7 @@
 								if ( -1 == $c_rel_type || 0 == $c_rel_bug ) {
 									PRINT lang_get( 'any' );
 								} else {
-								    PRINT relationship_get_description_for_history ($c_rel_type) . ' ' . $c_rel_bug;
+									PRINT relationship_get_description_for_history ($c_rel_type) . ' ' . $c_rel_bug;
 								}

 							?>
@@ -2385,13 +2386,13 @@
 				?>
 			</td>
 			<td class="small-caption" valign="top" id="tag_string_filter_target" colspan="5">
-				<?php
+				<?php
 					$t_tag_string = $t_filter['tag_string'];
 					if ( $t_filter['tag_select'] != 0 ) {
 						$t_tag_string .= ( is_blank( $t_tag_string ) ? '' : config_get( 'tag_separator' ) );
 						$t_tag_string .= tag_get_field( $t_filter['tag_select'], 'name' );
 					}
-					PRINT $t_tag_string
+					PRINT $t_tag_string
 				?>
 				<input type="hidden" name="tag_string" value="<?php echo $t_tag_string ?>"/>
 			</td>
@@ -2519,7 +2520,7 @@
 							foreach( $t_filter['custom_fields'][$t_accessible_custom_fields_ids[$i]] as $t_current ) {
 								$t_current = stripslashes( $t_current );
 								$t_this_string = '';
-								if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
+								if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
 										|| ( is_blank( $t_current ) ) ) {
 									$t_any_found = true;
 								} else if ( ( META_FILTER_NONE == $t_current ) && ( is_numeric( $t_current ) ) ) {
@@ -2602,11 +2603,11 @@
 								echo ", ";
 							}
 							$t_sort = $t_sort_fields[$i];
-        					if ( strpos( $t_sort, 'custom_' ) === 0 ) {
-        						$t_field_name = string_display( lang_get_defaulted( substr( $t_sort, strlen( 'custom_' ) ) ) );
-        					} else {
-        						$t_field_name = string_get_field_name( $t_sort );
-        					}
+							if ( strpos( $t_sort, 'custom_' ) === 0 ) {
+								$t_field_name = string_display( lang_get_defaulted( substr( $t_sort, strlen( 'custom_' ) ) ) );
+							} else {
+								$t_field_name = string_get_field_name( $t_sort );
+							}

 							echo $t_field_name . " " . lang_get( 'bugnote_order_' . strtolower( $t_dir_fields[$i] ) );
 							echo "<input type=\"hidden\" name=\"sort_$i\" value=\"$t_sort_fields[$i]\" />";
@@ -2652,7 +2653,7 @@
 							}
 						?>
 					</td>
-					<?php
+					<?php
 					if ( $t_filter_cols > 6 ) {
 						echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 5 ) . '">&nbsp;</td>';
 					}
@@ -2660,7 +2661,7 @@
 					if ( $t_filter_cols > 3 ) {
 						echo '<td class="small-caption" valign="top" colspan="' . ( $t_filter_cols - 2 ) . '">&nbsp;</td>';
 					}
-				}
+				}
 			?>
 		</tr>
 		<?php
@@ -2692,9 +2693,9 @@
 							print_bracket_link( $f_switch_view_link . 'advanced', lang_get( 'advanced_filters' ) );
 						}

-						print_bracket_link(
-							'permalink_page.php?url=' . urlencode( filter_get_url( $t_filter ) ),
-							lang_get( 'create_filter_link' ),
+						print_bracket_link(
+							'permalink_page.php?url=' . urlencode( filter_get_url( $t_filter ) ),
+							lang_get( 'create_filter_link' ),
 							/* new window = */ true );
 					}
 				?>
@@ -2769,7 +2770,7 @@

 		# check that the user can save non current filters (if required)
 		if ( ( ALL_PROJECTS <= $c_project_id ) && ( !is_blank( $p_name ) ) &&
-		     ( !access_has_project_level( config_get( 'stored_query_create_threshold' ) ) ) ) {
+			 ( !access_has_project_level( config_get( 'stored_query_create_threshold' ) ) ) ) {
 			return -1;
 		}

@@ -2790,7 +2791,7 @@

 			$query = "UPDATE $t_filters_table
 					  SET is_public='$c_is_public',
-					  	filter_string='$c_filter_string'
+						filter_string='$c_filter_string'
 					  WHERE id='" . $row['id'] . "'";
 			db_query( $query );

@@ -2882,8 +2883,8 @@
 		$query = "SELECT *
 				  FROM $t_filters_table
 				  WHERE user_id='$c_user_id'
-				  	AND project_id='$c_project_id'
-				  	AND name=''";
+					AND project_id='$c_project_id'
+					AND name=''";
 		$result = db_query( $query );

 		if ( db_num_rows( $result ) > 0 ) {
@@ -3048,7 +3049,7 @@
 		if ( !isset( $p_filter_arr['dir'] ) ) {
 			$p_filter_arr['dir'] = "DESC";
 		}
-
+
 		if ( !isset( $p_filter_arr['platform'] ) ) {
 			$p_filter_arr['platform'] = array( 0 => META_FILTER_ANY );
 		}
@@ -3140,15 +3141,15 @@
 			if ( isset( $t_sort_fields[$i] ) ) {
 				$t_drop = false;
 				$t_sort = $t_sort_fields[$i];
-        		if ( strpos( $t_sort, 'custom_' ) === 0 ) {
-        			if ( false === custom_field_get_id_from_name( substr( $t_sort, strlen( 'custom_' ) ) ) ) {
-        				$t_drop = true;
-        			}
-        		} else {
-        			if ( ! in_array( $t_sort, $t_fields ) ) {
-        				$t_drop = true;
-        			}
-        		}
+				if ( strpos( $t_sort, 'custom_' ) === 0 ) {
+					if ( false === custom_field_get_id_from_name( substr( $t_sort, strlen( 'custom_' ) ) ) ) {
+						$t_drop = true;
+					}
+				} else {
+					if ( ! in_array( $t_sort, $t_fields ) ) {
+						$t_drop = true;
+					}
+				}
 				if ( ! in_array( $t_dir_fields[$i], array( "ASC", "DESC" ) ) ) {
 					$t_drop = true;
 				}
@@ -3240,6 +3241,612 @@
 		return $p_filter_arr;
 	}

+	# Returns an array of the pre-defined filters
+	function filter_get_predefined ( $p_filter = false ) {
+		static $cache;
+
+		if (!isset($cache)) {
+
+			$t_bug_resolved_status_threshold = config_get( 'bug_resolved_status_threshold' );
+			$t_hide_status_default = config_get( 'hide_status_default' );
+			$t_default_show_changed = config_get( 'default_show_changed' );
+			$t_current_user_id = auth_get_current_user_id();
+
+			$cache = array();
+
+			$cache[ FILTER_ASSIGNED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => $t_current_user_id ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_bug_resolved_status_threshold ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_assigned' ),
+					'url' => 'handler_id=' . $t_current_user_id . '&amp;hide_status=' . $t_bug_resolved_status_threshold,
+					'id' => FILTER_ASSIGNED
+				);
+
+			$cache[ FILTER_RECENT_MOD ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => META_FILTER_NONE ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_recent_mod' ),
+					'url' => 'hide_status=none',
+					'id' => FILTER_RECENT_MOD
+				);
+
+			$cache[ FILTER_REPORTED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => $t_current_user_id ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'sort'			=> 'last_updated',
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_reported' ),
+					'url' => 'reporter_id=' . $t_current_user_id . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_REPORTED
+				);
+
+			$cache[ FILTER_RESOLVED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => $t_bug_resolved_status_threshold ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_resolved' ),
+					'url' => 'show_status=' . $t_bug_resolved_status_threshold . '&amp;hide_status=' . $t_bug_resolved_status_threshold,
+					'id' => FILTER_RESOLVED
+				);
+
+			$cache[ FILTER_UNASSIGNED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_NONE ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_unassigned' ),
+					'url' => 'handler_id=[none]' . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_UNASSIGNED
+				);
+
+			$cache[ FILTER_MONITORED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => $t_current_user_id )
+						),
+					'name' => lang_get( 'my_view_title_monitored' ),
+					'url' => 'user_monitor=' . $t_current_user_id . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_MONITORED
+				);
+
+
+			$cache[ FILTER_FEEDBACK ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => FEEDBACK ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => $t_current_user_id ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_feedback' ),
+					'url' => 'reporter_id=' . $t_current_user_id . '&amp;show_status=' . FEEDBACK . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_FEEDBACK
+				);
+
+			$cache[ FILTER_VERIFY ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => $t_bug_resolved_status_threshold ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => $t_current_user_id ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_verify' ),
+					'url' => 'reporter_id=' . $t_current_user_id . '&amp;show_status=' . $t_bug_resolved_status_threshold,
+					'id' => FILTER_VERIFY
+				);
+
+		}
+
+		if (is_bool($p_filter) || empty($p_filter))
+			return $cache;
+		else if (array_key_exists($p_filter, $cache))
+			return $cache[ $p_filter ];
+		else
+			return false;
+
+	}
+
+	# Returns an array of the default filters for my view
+	function filter_get_default_my_view ( $p_project_id = ALL_PROJECTS ) {
+
+		$t_current_user_id = auth_get_current_user_id();
+
+		# Pull the list of My View boxes per access level
+		$t_access_boxes = config_get( 'my_view_access_boxes' );
+		$t_user_level = access_get_project_level( $p_project_id );
+
+		# If they don't have a custom view by access level, give them the default
+		if (array_key_exists($t_user_level, $t_access_boxes))
+			$t_config_boxes = $t_access_boxes[ $t_user_level ];
+		else
+			$t_config_boxes = config_get( 'my_view_boxes' );
+
+
+		$return = array();
+
+		foreach ($t_config_boxes AS $box) {
+
+			# if box is less than 0, that means it's a predefined box
+			if ($box < 0) {
+				$return[ $box ] = filter_get_predefined( $box );
+			}
+
+			# otherwise, we need to get this filter from the database
+			else {
+				$return[ $box ] = filter_get_row( $box );
+				if (!$return[ $box ])
+					unset ($return[ $box ]);
+				else
+					$return[ $box ]['filter'] = filter_deserialize( $return[ $box ]['filter_string'] );
+			}
+		}
+
+		# don't display "Assigned to Me" bugs to users that bugs can't be assigned to
+		if ( current_user_is_anonymous() || user_get_assigned_open_bug_count( $t_current_user_id, $p_project_id ) == 0 )
+			unset( $return[FILTER_ASSIGNED] );
+
+		# don't display "Monitored by Me" bugs to users that can't monitor bugs
+		if ( current_user_is_anonymous() OR !access_has_project_level( config_get( 'monitor_bug_threshold' ), $p_project_id, $t_current_user_id ) )
+			unset( $return[FILTER_MONITORED] );
+
+
+		# don't display "Reported by Me" bugs to users that can't report bugs
+		if ( current_user_is_anonymous() || !access_has_project_level( config_get( 'report_bug_threshold' ), $p_project_id, $t_current_user_id ) ) {
+			unset( $return[FILTER_REPORTED] );
+			unset( $return[FILTER_FEEDBACK] );
+			unset( $return[FILTER_VERIFY] );
+		}
+
+		return $return;
+	}
+
+	# Returns a list of filters specific to a user for their my_view page
+	function filter_db_get_my_view ( $p_user_id = false ) {
+
+		if (is_bool($p_user_id) || empty($p_user_id))
+			$p_user_id = auth_get_current_user_id();
+
+		$t_filters_my_view_table    = config_get( 'mantis_filters_my_view_table' );
+		$t_filters_table            = config_get( 'mantis_filters_table' );
+
+		$t_user_id = db_prepare_int( $p_user_id );
+
+		$query = "SELECT *
+
+					FROM $t_filters_my_view_table
+					  AS FMV
+
+			   LEFT JOIN $t_filters_table
+					  AS FM
+					  ON FMV.filter_id = FM.id
+
+				   WHERE FMV.user_id = $t_user_id
+					 AND ( "
+
+					 # If the user doesn't have access rights to stored queries, return only predefined filters
+					 .(access_has_project_level( config_get( 'stored_query_use_threshold' ) )?"FM.id IS NOT NULL OR ":"")
+
+					 ." FMV.filter_id < 0 )
+				ORDER BY FMV.sequence ASC";
+
+		$result = db_query( $query );
+		$query_count = db_num_rows( $result );
+
+		if ($query_count <= 0)
+			return array();
+
+		$t_filter_arr = array();
+
+		for ( $i = 0; $i < $query_count; $i++ ) {
+			$row = db_fetch_array( $result );
+
+			# if it is less than 0, that means it is a predefined filter
+			if (intval($row['filter_id']) < 0) {
+				$t_filter_arr[ intval($row['filter_id']) ] = filter_get_predefined( intval($row['filter_id']) );
+			}
+			else {
+				$t_filter_arr[ intval($row['filter_id']) ] = $row;
+				$t_filter_arr[ intval($row['filter_id']) ]['filter'] = filter_deserialize( $row['filter_string'] );
+			}
+
+			// Perform some sequence cleanup
+			if ($row['sequence'] != $i + 1)
+				filter_set_filter_sequence( $i + 1, $row['filter_id'], $t_user_id );
+
+			$t_filter_arr[ intval($row['filter_id']) ]['sequence'] = $i + 1;
+		}
+
+		return $t_filter_arr;
+	}
+
+	# Returns the next sequence value for a user
+	function filter_get_next_sequence ( $p_user_id ) {
+
+		$t_filters_my_view_table    = config_get( 'mantis_filters_my_view_table' );
+		$t_user_id = db_prepare_int( $p_user_id );
+
+		$query = "SELECT MAX(sequence) AS max
+					FROM $t_filters_my_view_table
+				   WHERE user_id = ". $t_user_id;
+
+		$result = db_query($query);
+		$row = db_fetch_array( $result );
+
+		return intval($row['max']) + 1;
+	}
+
+	# Returns boolean whether a filter exists
+	# $p_predefined allows you to set whether or not a predefined filter ID will return true or not
+	function filter_exists ( $p_filter_id, $p_user_id = null, $p_project_id = null, $p_predefined = true) {
+
+		# If less than zero, it must be a predefined filter ID
+		if ($p_filter_id < 0) {
+			if ($p_predefined && filter_get_predefined($p_filter_id))
+				return true;
+			else
+				return false;
+		}
+
+		# I used filter_cache_row instead of filter_get_row so I can control the errors
+		$filter = filter_cache_row( $p_filter_id, false );
+
+		if (!$filter)
+			return false;
+
+		else if (!is_null($p_user_id) && $p_user_id != $filter['user_id'])
+			return false;
+
+		else if (!is_null($p_project_id) && $p_project_id != $filter['project_id'])
+			return false;
+
+		return true;
+	}
+
+	# Removes a filter from a users 'My View'
+	function filter_remove_from_my_view ( $p_filter_id, $p_user_id = null ) {
+
+		if ( empty($p_user_id) || is_bool($p_user_id) )
+			$p_user_id = auth_get_current_user_id();
+
+		$t_filters_my_view_table    = config_get( 'mantis_filters_my_view_table' );
+
+		$c_user_id		= db_prepare_int( $p_user_id );
+		$c_filter_id	= db_prepare_int( $p_filter_id );
+
+		# First, we need to get the sequence of this filter so we can adjust order
+		$query = "SELECT sequence
+					FROM $t_filters_my_view_table
+				   WHERE filter_id = $c_filter_id
+					 AND user_id = $c_user_id
+				   LIMIT 1";
+
+		$result = db_query($query);
+
+		if (db_num_rows( $result ) <= 0)
+			return true;
+
+		$t_sequence = db_fetch_array( $result );
+		$t_sequence = db_prepare_int($t_sequence['sequence']);
+
+		$query = "DELETE FROM $t_filters_my_view_table
+						WHERE filter_id = $c_filter_id
+						  AND user_id = $c_user_id
+						LIMIT 1";
+
+		db_query($query);
+
+		$query = "UPDATE $t_filters_my_view_table
+					 SET sequence = sequence - 1
+				   WHERE sequence > $t_sequence
+					 AND user_id = $c_user_id";
+
+		db_query( $query );
+
+		return true;
+	}
+
+	# adds a new filter to a users 'My View'
+	function filter_add_to_my_view ($p_filter_id, $p_user_id = null) {
+
+		if ( empty($p_user_id) || is_bool($p_user_id) )
+			$p_user_id = auth_get_current_user_id();
+
+		$c_filter_id		= db_prepare_int( $p_filter_id );
+		$c_user_id			= db_prepare_int( $p_user_id );
+
+		# We can't add a non-existent filter
+		if ( !filter_exists( $c_filter_id, $c_user_id ) )
+			return false;
+
+		$t_filters_my_view_table    = config_get( 'mantis_filters_my_view_table' );
+
+		$query = "INSERT INTO $t_filters_my_view_table
+						  SET filter_id = $c_filter_id,
+							  user_id = $c_user_id,
+							  sequence = ". filter_get_next_sequence( $c_user_id );
+
+		db_query( $query );
+
+		return true;
+
+	}
+
+	# updates the sequence for a filter
+	function filter_set_filter_sequence ($p_sequence, $p_filter_id, $p_user_id = null) {
+
+		if ( empty($p_user_id) || is_bool($p_user_id) )
+			$p_user_id = auth_get_current_user_id();
+
+		$c_filter_id		= db_prepare_int( $p_filter_id );
+		$c_user_id			= db_prepare_int( $p_user_id );
+		$c_sequence			= db_prepare_int( $p_sequence );
+
+		$t_filters_my_view_table    = config_get( 'mantis_filters_my_view_table' );
+
+		$query = "UPDATE $t_filters_my_view_table
+					 SET sequence = $c_sequence
+				   WHERE filter_id = $c_filter_id
+					 AND user_id = $c_user_id
+				   LIMIT 1";
+
+		db_query( $query );
+
+	}
+
+	# Prints a select box for adding filters
+	function print_filter_my_view_inactive ( $p_show_empty = true ) {
+
+		$p_user_id = auth_get_current_user_id();
+
+		# Get the filters the user currently displays on their My View
+		$t_active = array_keys( filter_db_get_my_view() );
+
+		# Get all the predefined filters, then weed out the ones they have already set
+		$t_predefined = filter_get_predefined();
+		foreach ($t_predefined AS $key => $filter) {
+			if (in_array($key, $t_active))
+				unset($t_predefined[$key]);
+			else
+				$t_predefined[ $key ] = $filter['name'];
+		}
+
+		if ( access_has_project_level( config_get( 'stored_query_use_threshold' ) ) ) {
+
+			# Get all the available filters, then weed out the ones already in use
+			$t_available = filter_db_get_available_queries( ALL_PROJECTS, $p_user_id );
+			foreach ($t_available AS $key => $filter) {
+				if (in_array($key, $t_active))
+					unset($t_available[$key]);
+			}
+
+		} else {
+			$t_available = array();
+		}
+
+		# If both lists are empty, don't show the form unless they want us to
+		if (count($t_predefined) <= 0 && count($t_available) <= 0 && !$p_show_empty)
+			return;
+
+		?>
+		<form action="account_my_view_add.php" method="post">
+		<select name="filter_id">
+			<?php
+
+			if (count($t_available) > 0) {
+				echo "<optgroup label='". lang_get('custom_filters') ."'>";
+
+				foreach ($t_available AS $f_key => $f_title) {
+					echo "<option value='". $f_key ."'>" . string_display_line($f_title) . "</option>";
+				}
+				echo "</optgroup>";
+			}
+
+			if (count($t_predefined) > 0) {
+				echo "<optgroup label='". lang_get('predefined_filters') ."'>";
+
+				foreach ($t_predefined AS $f_key => $f_title) {
+					echo "<option value='". $f_key ."'>". string_display_line($f_title) ."</option>";
+				}
+				echo "</optgroup>";
+			}
+
+			?>
+		</select>
+		<input type="submit" class="button" value="<?php echo lang_get('add_my_view_filter'); ?>" />
+		</form>
+		<?php
+	}
+
+	# Prints a my view box from a set of query results
+	function print_filter_my_view_box ( $p_title, $p_page_number, $p_per_page, $p_custom_filter,
+										$p_project_id, $p_user_id, $p_show_sticky = null, $p_url = null, $p_show_empty = TRUE ) {
+
+		$t_page_count = 0;
+		$t_bug_count = 0;
+
+		# Run the filter query
+		$result = filter_get_bug_rows( $p_page_number, $p_per_page, $t_page_count, $t_bug_count,
+									$p_custom_filter, $p_project_id, $p_user_id, $p_show_sticky );
+
+		if (count($result) == 0 && !$p_show_empty)
+			return;
+
+		if (is_null($p_url))
+			$p_url = filter_get_url( $p_custom_filter );
+
+		$t_icon_path = config_get( 'icon_path' );
+		$t_update_bug_threshold = config_get( 'update_bug_threshold' );
+
+		?>
+		<table class="width100" cellspacing="1">
+			<tr>
+				<td class="form-title" colspan="2">
+					<a class="subtle" href="<?php echo $p_url; ?>"><?php echo string_display_line($p_title); ?></a>
+					[<a class="subtle" href="<?php echo $p_url; ?>" target="_blank">^</a>]
+					( <?php echo string_display_line(project_get_name( $p_project_id )); ?> )
+					<?php
+						if ( count( $result ) > 0 ) {
+							$v_start = $p_per_page * ($p_page_number - 1) + 1;
+							$v_end   = $v_start + count( $result ) - 1;
+						} else {
+							$v_start = 0;
+							$v_end   = 0;
+						}
+						echo "($v_start - $v_end / $t_bug_count)";
+					?>
+				</td>
+			</tr>
+			<?php
+			foreach ($result AS $row) {
+
+				?>
+				<tr bgcolor="<?php echo get_status_color($row['status']) ?>">
+
+					<td class="center">
+						<span class="small">
+						<?php
+							print_bug_link( $row['id'] );
+
+							echo '<br />';
+
+							if ( !bug_is_readonly( $row['id'] ) && access_has_bug_level( $t_update_bug_threshold, $row['id'] ) ) {
+								echo '<a href="' . string_get_bug_update_url( $row['id'] ) . '"><img border="0" src="' . $t_icon_path . 'update.png' . '" alt="' . lang_get( 'update_bug_button' ) . '" /></a>';
+							}
+
+							if ( ON == config_get( 'show_priority_text' ) ) {
+								print_formatted_priority_string( $row['status'], $row['priority'] );
+							} else {
+								print_status_icon( $row['priority'] );
+							}
+
+							$t_attachment_count = 0;
+							if (  ( file_can_view_bug_attachments( $row['id'] ) ) ) {
+							   $t_attachment_count = file_bug_attachment_count( $row['id'] );
+							}
+
+							if ( 0 < $t_attachment_count ) {
+								echo '<a href="' . string_get_bug_view_url( $row['id'] ) . '#attachments">';
+								echo '<img border="0" src="' . $t_icon_path . 'attachment.png' . '"';
+								echo ' alt="' . lang_get( 'attachment_alt' ) . '"';
+								echo ' title="' . $t_attachment_count . ' ' . lang_get( 'attachments' ) . '"';
+								echo ' />';
+								echo '</a>';
+							}
+							if ( VS_PRIVATE == $row['view_state'] ) {
+								echo '<img src="' . $t_icon_path . 'protected.gif" width="8" height="15" alt="' . lang_get( 'private' ) . '" />';
+							}
+						?>
+						</span>
+					</td>
+					<td class="left" valign="top" width="100%">
+						<span class="small">
+						<?php
+
+							echo string_attribute( $row['summary'] )
+								.'<br />';
+							# show project name if viewing 'all projects' or bug is in subproject
+							if ( ON == config_get( 'show_bug_project_links' ) &&
+								helper_get_current_project() != $row['project_id'] ) {
+								echo '['. project_get_name($row['project_id']) .'] ';
+							}
+
+							echo string_display( $row['category'] );
+
+							$t_last_updated = date( config_get( 'normal_date_format' ), $row['last_updated'] );
+
+							if ( $row['last_updated'] > strtotime( '-'. $p_custom_filter['highlight_changed'] .' hours' ) ) {
+								echo ' - <b>' . $t_last_updated . '</b>';
+							} else {
+								echo ' - ' . $t_last_updated;
+							}
+
+						?>
+						</span>
+					</td>
+				</tr>
+				<?php
+			}
+			?>
+		</table>
+
+		<?
+
+	}
+
+

 	/**
 	 * The following functions each print out an individual filter field.
@@ -3345,7 +3952,7 @@
 		</select>
 		<?php
 	}
-
+
 	function print_filter_platform() {
 		global $t_select_modifier, $t_filter;

@@ -3353,7 +3960,7 @@
 		<!-- Platform -->
 		<select <?php echo $t_select_modifier;?> name="platform[]">
 			<option value="<?php echo META_FILTER_ANY ?>" <?php check_selected( $t_filter['platform'], META_FILTER_ANY ); ?>>[<?php echo lang_get( 'any' ) ?>]</option>
-			<?php
+			<?php
 				log_event( LOG_FILTERING, 'Platform = ' . var_export( $t_filter['platform'], true ) );
 				print_platform_option_list( $t_filter['platform'] );
 			?>
@@ -3472,10 +4079,10 @@
 	function print_filter_show_priority(){
 		global $t_select_modifier, $t_filter;
 		?><!-- Priority -->
-    <select <?php PRINT $t_select_modifier;?> name="show_priority[]">
+	<select <?php PRINT $t_select_modifier;?> name="show_priority[]">
 			<option value="<?php echo META_FILTER_ANY ?>" <?php check_selected( $t_filter['show_priority'], META_FILTER_ANY ); ?>>[<?php echo lang_get( 'any' ) ?>]</option>
 			<?php print_enum_string_option_list( 'priority', $t_filter['show_priority'] ) ?>
-    </select>
+	</select>
 		<?php
 	}

@@ -3684,11 +4291,11 @@
 		$t_shown_fields[""] = "";
 		for ( $i=0; $i < $t_n_fields; $i++ ) {
 			if ( !in_array( $t_fields[$i], array( 'selection', 'edit', 'bugnotes_count', 'attachment' ) ) ) {
-        		if ( strpos( $t_fields[$i], 'custom_' ) === 0 ) {
-        			$t_field_name = string_display( lang_get_defaulted( substr( $t_fields[$i], strlen( 'custom_' ) ) ) );
-        		} else {
-        			$t_field_name = string_get_field_name( $t_fields[$i] );
-        		}
+				if ( strpos( $t_fields[$i], 'custom_' ) === 0 ) {
+					$t_field_name = string_display( lang_get_defaulted( substr( $t_fields[$i], strlen( 'custom_' ) ) ) );
+				} else {
+					$t_field_name = string_get_field_name( $t_fields[$i] );
+				}
 				$t_shown_fields[$t_fields[$i]] = $t_field_name;
 			}
 		}
@@ -3867,7 +4474,7 @@
 		</select>
 		<?php
 	}
-
+
 	# Prints a multi-value filter field.  For example, platform, etc.
 	# $p_field_name - The name of the field, e.g. "platform"
 	# $p_field_value - an array of values.
@@ -3879,7 +4486,7 @@
 			echo lang_get( 'any' );
 		} else {
 			$t_first_flag = true;
-
+
 			$t_field_value = is_array( $p_field_value ) ? $p_field_value : array( $p_field_value );

 			foreach( $t_field_value as $t_current ) {
@@ -3889,7 +4496,7 @@
 				<?php
 				$t_this_string = '';

-				if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
+				if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) )
 						|| ( is_blank( $t_current ) ) ) {
 					$t_any_found = true;
 				} else {
@@ -3993,7 +4600,7 @@
 			return '';
 		}
 	}
-
+
 	# --------------------
 	# Checks if a filter value is "any".  Supports both single value as well as multiple value
 	# fields (array).
Index: core/html_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/html_api.php,v
retrieving revision 1.219
diff -u -r1.219 html_api.php
--- core/html_api.php	22 Oct 2007 07:05:45 -0000	1.219
+++ core/html_api.php	23 Oct 2007 17:39:03 -0000
@@ -63,7 +63,7 @@

 	# flag for error handler to skip header menus
 	$g_error_send_page_header = true;
-
+
 	# Projax library disabled by default.  It will be enabled if projax_api.php
 	# is included.  But it must be included after html_api.php
 	$g_enable_projax = false;
@@ -750,18 +750,25 @@
 	function print_account_menu( $p_page='' ) {
 		$t_account_page 				= 'account_page.php';
 		$t_account_prefs_page 			= 'account_prefs_page.php';
+		$t_account_my_view_page 		= 'account_my_view_page.php';
 		$t_account_profile_menu_page 	= 'account_prof_menu_page.php';
 		$t_account_sponsor_page			= 'account_sponsor_page.php';

 		switch ( $p_page ) {
 			case $t_account_page				: $t_account_page 				= ''; break;
 			case $t_account_prefs_page			: $t_account_prefs_page 		= ''; break;
+			case $t_account_my_view_page		: $t_account_my_view_page 		= ''; break;
 			case $t_account_profile_menu_page	: $t_account_profile_menu_page 	= ''; break;
 			case $t_account_sponsor_page		: $t_account_sponsor_page		= ''; break;
 		}

 		print_bracket_link( $t_account_page, lang_get( 'account_link' ) );
 		print_bracket_link( $t_account_prefs_page, lang_get( 'change_preferences_link' ) );
+
+
+		if (access_has_global_level(config_get('custom_my_view_threshold')))
+			print_bracket_link( $t_account_my_view_page, lang_get( 'my_view_link' ) );
+
 		if ( access_has_project_level( config_get( 'add_profile_threshold' ) ) ) {
 			print_bracket_link( $t_account_profile_menu_page, lang_get( 'manage_profiles_link' ) );
 		}
@@ -911,22 +918,22 @@
 		if ( null === $p_fields ) {
 			$p_fields = array();
 		}
-
+
 		if ( strtolower( $p_method ) == 'get' ) {
 			$t_method = 'get';
 		} else {
 			$t_method = 'post';
 		}
-
+
 		PRINT "<form method=\"$t_method\" action=\"$p_action\">\n";
-
+
 		foreach ( $p_fields as $key => $val ) {
 			$key = string_attribute( $key );
 			$val = string_attribute( $val );
-
+
 			PRINT "	<input type=\"hidden\" name=\"$key\" value=\"$val\" />\n";
 		}
-
+
 		PRINT "	<input type=\"submit\" class=\"button\" value=\"$p_button_text\" />\n";
 		PRINT "</form>\n";
 	}
@@ -1222,7 +1229,7 @@
 	 * @param integer Tag ID
 	 */
 	function html_button_tag_update( $p_tag_id ) {
-		if ( access_has_global_level( config_get( 'tag_edit_threshold' ) )
+		if ( access_has_global_level( config_get( 'tag_edit_threshold' ) )
 			|| ( auth_get_current_user_id() == tag_get_field( $p_tag_id, 'user_id' )
 				&& access_has_global_level( config_get( 'tag_edit_own_threshold' ) ) ) )
 		{
Index: lang/strings_english.txt
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/lang/strings_english.txt,v
retrieving revision 1.316
diff -u -r1.316 strings_english.txt
--- lang/strings_english.txt	22 Sep 2007 22:51:15 -0000	1.316
+++ lang/strings_english.txt	23 Oct 2007 17:39:04 -0000
@@ -1432,4 +1432,10 @@
 $s_graph_page = 'Graph Bug History';
 $s_graph_bug_page_link = 'Graph';

-?>
+# Custom Filtering
+$s_add_my_view_filter = 'Add Filter to My View';
+$s_my_view_filters = 'My View Filters';
+$s_predefined_filters = 'Predefined Filters';
+$s_custom_filters = 'Custom Filters';
+
+?>
\ No newline at end of file
customMyView.diff (70,617 bytes)
Nycto

Nycto

2007-10-23 13:56

reporter   ~0015958

While implementing Mantis for my company I set-up this feature. I have attached an archive to this note with a diff file, 4 new files and a readme that describes installation and use.

2007-10-23 13:57

 

customMyView.tar.gz (19,887 bytes)
jreese

jreese

2007-10-23 14:43

reporter   ~0015959

Can you resubmit a diff that does not contain useless add/remove blocks? Perhaps your file editor needs to be set to use Unix-style line feed like the rest of the Mantis codebase, rather than windows style carriage returns.

2007-10-23 15:41

 

customMyView_v2.tar.gz (10,282 bytes)

2007-10-23 15:41

 

customMyView_v2.diff (33,697 bytes)
? account_my_view_add.php
? account_my_view_delete.php
? account_my_view_page.php
? account_my_view_sequence.php
Index: config_defaults_inc.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/config_defaults_inc.php,v
retrieving revision 1.365
diff -u -b -r1.365 config_defaults_inc.php
--- config_defaults_inc.php	4 Oct 2007 05:59:04 -0000	1.365
+++ config_defaults_inc.php	23 Oct 2007 19:23:21 -0000
@@ -1352,6 +1352,7 @@
 	$g_mantis_custom_field_string_table     = '%db_table_prefix%_custom_field_string%db_table_suffix%';
 	$g_mantis_upgrade_table					= '%db_table_prefix%_upgrade%db_table_suffix%';
 	$g_mantis_filters_table					= '%db_table_prefix%_filters%db_table_suffix%';
+	$g_mantis_filters_my_view_table			= '%db_table_prefix%_filters_my_view%db_table_suffix%';
 	$g_mantis_sponsorship_table				= '%db_table_prefix%_sponsorship%db_table_suffix%';
 	$g_mantis_tokens_table					= '%db_table_prefix%_tokens%db_table_suffix%';
 	$g_mantis_project_hierarchy_table		= '%db_table_prefix%_project_hierarchy%db_table_suffix%';
@@ -1675,19 +1676,37 @@
 	# Number of bugs shown in each box
 	$g_my_view_bug_count = 10;
 
-	# Boxes to be shown and their order
-	# A box that is not to be shown can have its value set to 0
+	# Boxes to be shown in "My View". Put them in the order you want them to appear
 	$g_my_view_boxes = array (
-		'assigned'      => '1',
-		'unassigned'    => '2',
-		'reported'      => '3',
-		'resolved'      => '4',
-		'recent_mod'	=> '5',
-		'monitored'		=> '6',
-		'feedback'		=> '0',
-		'verify'		=> '0'
+		FILTER_ASSIGNED,
+		FILTER_UNASSIGNED,
+		FILTER_REPORTED,
+		FILTER_RESOLVED,
+		FILTER_RECENT_MOD,
+		FILTER_MONITORED,
+		// FILTER_FEEDBACK,
+		// FILTER_VERIFY,
 	);
 
+	# Allows you to set a custom "My View" on an access level basis
+	# To do this, set the key of the first dimension to the access level, then
+	# make the value an array of filters. For example:
+	# $g_my_view_access_boxes = array (
+	# 	ADMINISTRATOR => array(
+	#		FILTER_UNASSIGNED,
+	#		FILTER_ASSIGNED
+	#	),
+	#   REPORTER => array(
+	#		FILTER_REPORTED,
+	#		FILTER_MONITORED
+	#	)
+	# );
+	$g_my_view_access_boxes = array (
+	);
+
+	# threshold needed to customize the 'My View' screen
+	$g_custom_my_view_threshold = ANYBODY;
+
 	# Toggle whether 'My View' boxes are shown in a fixed position (i.e. adjacent boxes start at the same vertical position)
 	$g_my_view_boxes_fixed_position = ON;
 
Index: my_view_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/my_view_page.php,v
retrieving revision 1.17
diff -u -b -r1.17 my_view_page.php
--- my_view_page.php	28 Jul 2007 10:15:15 -0000	1.17
+++ my_view_page.php	23 Oct 2007 19:23:21 -0000
@@ -17,6 +17,7 @@
 	require_once( $t_core_path . 'compress_api.php' );
 	require_once( $t_core_path . 'filter_api.php' );
 	require_once( $t_core_path . 'last_visited_api.php' );
+	require_once( $t_core_path . 'icon_api.php' );
 
 	auth_ensure_user_authenticated();
 
@@ -40,11 +41,6 @@
 	$t_bug_count = null;
 	$t_page_count = null;
 
-	$t_boxes = config_get( 'my_view_boxes' );
-	asort ($t_boxes);
-	reset ($t_boxes);
-	#print_r ($t_boxes);
-
 	$t_project_id = helper_get_current_project();
 ?>
 
@@ -61,52 +57,76 @@
 		echo '</td>';
 		echo '</tr>';
 	}
-?>
 
-<?php
-	$t_number_of_boxes = count ( $t_boxes );
 	$t_boxes_position = config_get( 'my_view_boxes_fixed_position' );
-	$t_counter = 0;
 
-	while (list ($t_box_title, $t_box_display) = each ($t_boxes)) {
-		# don't display bugs that are set as 0
-		if ($t_box_display == 0) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+	$t_custom_my_view_threshold = config_get('custom_my_view_threshold');
 
-		# don't display "Assigned to Me" bugs to users that bugs can't be assigned to
-		else if ( $t_box_title == 'assigned' && ( current_user_is_anonymous() OR user_get_assigned_open_bug_count( $t_current_user_id, $t_project_id ) == 0 ) ) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+	# Make sure they have access to define a custom 'my view'
+	if (access_has_global_level($t_custom_my_view_threshold)) {
 
-		# don't display "Monitored by Me" bugs to users that can't monitor bugs
-		else if ( $t_box_title == 'monitored' && ( current_user_is_anonymous() OR !access_has_project_level( config_get( 'monitor_bug_threshold' ), $t_project_id, $t_current_user_id ) ) ) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+		# Get the list of custom my_view filters
+		$t_filters = filter_db_get_my_view( $t_current_user_id, TRUE );
 
-		# don't display "Reported by Me" bugs to users that can't report bugs
-		else if ( in_array( $t_box_title, array( 'reported', 'feedback', 'verify' ) ) && 
-				( current_user_is_anonymous() OR !access_has_project_level( config_get( 'report_bug_threshold' ), $t_project_id, $t_current_user_id ) ) ) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+		# If they set no custom filters, then get the default view
+		if (count($t_filters) <= 0)
+			$t_filters = filter_get_default_my_view( $t_project_id );
 
-		# display the box
+	}
 		else {
+		$t_filters = filter_get_default_my_view( $t_project_id );
+	}
+
+
+	$t_number_of_boxes = count($t_filters);
+
+	$t_counter = 0;
+
+	foreach ($t_filters AS $filter) {
+
 			$t_counter++;
 
-			# check the style of displaying boxes - fixed (ie. each box in a separate table cell) or not
+		# If the filter is for a specific project, only use that project
+		if (array_key_exists('project_id', $filter) && $filter['project_id'] != 0)
+			$t_filter_project_id = $filter['project_id'];
+		else
+			$t_filter_project_id = $t_project_id;
+
 			if ( ON == $t_boxes_position ) {
+
 				# for even box number start new row and column
-				if ( 1 == $t_counter%2 ) {
+			if ( 1 == $t_counter % 2 ) {
 					echo '<tr><td valign="top" width="50%">';
-					include( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'my_view_inc.php' );
+
+				print_filter_my_view_box(
+						$filter['name'],
+						$f_page_number,
+						$t_per_page,
+						$filter['filter'],
+						$t_filter_project_id,
+						$t_current_user_id,
+						null,
+						array_key_exists('url', $filter)?"view_all_set.php?type=1&amp;temporary=y&amp;". $filter['url']:null
+					);
+
 					echo '</td>';
 				}
 
 				# for odd box number only start new column
 				elseif ( 0 == $t_counter%2 ) {
 					echo '<td valign="top" width="50%">';
-					include( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'my_view_inc.php' );
+
+				print_filter_my_view_box(
+						$filter['name'],
+						$f_page_number,
+						$t_per_page,
+						$filter['filter'],
+						$t_filter_project_id,
+						$t_current_user_id,
+						null,
+						array_key_exists('url', $filter)?"view_all_set.php?type=1&amp;temporary=y&amp;". $filter['url']:null
+					);
+
 					echo '</td></tr>';
 				}
 
@@ -114,8 +134,10 @@
 				if ( ( $t_counter == $t_number_of_boxes ) && 1 == $t_counter%2 ) {
 					echo '<td valign="top" width="50%"></td></tr>';
 				}
+
 			}
-			else if ( OFF == $t_boxes_position ) {
+		else {
+
 				# start new table row and column for first box
 				if ( 1 == $t_counter ) {
 					echo '<tr><td valign="top" width="50%">';
@@ -127,7 +149,18 @@
 				}
 
 				# display the required box
-				include( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'my_view_inc.php' );
+
+			print_filter_my_view_box(
+					$filter['name'],
+					$f_page_number,
+					$t_per_page,
+					$filter['filter'],
+					$t_filter_project_id,
+					$t_current_user_id,
+					null,
+					array_key_exists('url', $filter)?"view_all_set.php?type=1&amp;temporary=y&amp;". $filter['url']:null
+				);
+
 				echo '<br />';
 
 				# close the first column for first half of boxes
@@ -140,12 +173,9 @@
 					echo '</td></tr>';
 				}
 			}
-		}
-	}
 
-?>
+	}
 
-<?php
 	if ( $t_status_legend_position == STATUS_LEGEND_POSITION_BOTTOM || $t_status_legend_position == STATUS_LEGEND_POSITION_BOTH ) {
 		echo '<tr>';
 		echo '<td colspan="2">';
Index: core/constant_inc.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/constant_inc.php,v
retrieving revision 1.74
diff -u -b -r1.74 constant_inc.php
--- core/constant_inc.php	24 Sep 2007 19:24:30 -0000	1.74
+++ core/constant_inc.php	23 Oct 2007 19:23:21 -0000
@@ -321,6 +321,16 @@
 	define( 'FILTER_POSITION_BOTTOM',			2 );
 	define( 'FILTER_POSITION_BOTH',				3 );  // FILTER_POSITION_TOP | FILTER_POSITION_BOTTOM (bitwise OR)
 
+	    # Default Filters
+	define( 'FILTER_ASSIGNED',					-1 );
+	define( 'FILTER_RECENT_MOD',				-2 );
+	define( 'FILTER_REPORTED',					-3 );
+	define( 'FILTER_RESOLVED',					-4 );
+	define( 'FILTER_UNASSIGNED',				-5 );
+	define( 'FILTER_MONITORED',					-6 );
+	define( 'FILTER_FEEDBACK',					-7 );
+	define( 'FILTER_VERIFY',					-8 );
+
 	# Flags for settings E-mail categories
 	define( 'EMAIL_CATEGORY_PROJECT_CATEGORY',	1);
 
Index: core/filter_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/filter_api.php,v
retrieving revision 1.164
diff -u -b -r1.164 filter_api.php
--- core/filter_api.php	19 Oct 2007 06:13:00 -0000	1.164
+++ core/filter_api.php	23 Oct 2007 19:23:21 -0000
@@ -426,6 +426,7 @@
 			$t_project_id	= $p_project_id;
 		}
 
+
 		if ( $p_custom_filter === null ) {
 			# Prefer current_user_get_bug_filter() over user_get_filter() when applicable since it supports
 			# cookies set by previous version of the code.
@@ -3240,6 +3241,612 @@
 		return $p_filter_arr;
 	}
 
+	# Returns an array of the pre-defined filters
+	function filter_get_predefined ( $p_filter = false ) {
+		static $cache;
+
+		if (!isset($cache)) {
+
+			$t_bug_resolved_status_threshold = config_get( 'bug_resolved_status_threshold' );
+			$t_hide_status_default = config_get( 'hide_status_default' );
+			$t_default_show_changed = config_get( 'default_show_changed' );
+			$t_current_user_id = auth_get_current_user_id();
+
+			$cache = array();
+
+			$cache[ FILTER_ASSIGNED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => $t_current_user_id ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_bug_resolved_status_threshold ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_assigned' ),
+					'url' => 'handler_id=' . $t_current_user_id . '&amp;hide_status=' . $t_bug_resolved_status_threshold,
+					'id' => FILTER_ASSIGNED
+				);
+
+			$cache[ FILTER_RECENT_MOD ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => META_FILTER_NONE ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_recent_mod' ),
+					'url' => 'hide_status=none',
+					'id' => FILTER_RECENT_MOD
+				);
+
+			$cache[ FILTER_REPORTED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => $t_current_user_id ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'sort'			=> 'last_updated',
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_reported' ),
+					'url' => 'reporter_id=' . $t_current_user_id . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_REPORTED
+				);
+
+			$cache[ FILTER_RESOLVED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => $t_bug_resolved_status_threshold ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_resolved' ),
+					'url' => 'show_status=' . $t_bug_resolved_status_threshold . '&amp;hide_status=' . $t_bug_resolved_status_threshold,
+					'id' => FILTER_RESOLVED
+				);
+
+			$cache[ FILTER_UNASSIGNED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_NONE ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_unassigned' ),
+					'url' => 'handler_id=[none]' . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_UNASSIGNED
+				);
+
+			$cache[ FILTER_MONITORED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => $t_current_user_id )
+						),
+					'name' => lang_get( 'my_view_title_monitored' ),
+					'url' => 'user_monitor=' . $t_current_user_id . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_MONITORED
+				);
+
+
+			$cache[ FILTER_FEEDBACK ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => FEEDBACK ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => $t_current_user_id ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_feedback' ),
+					'url' => 'reporter_id=' . $t_current_user_id . '&amp;show_status=' . FEEDBACK . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_FEEDBACK
+				);
+
+			$cache[ FILTER_VERIFY ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => $t_bug_resolved_status_threshold ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => $t_current_user_id ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_verify' ),
+					'url' => 'reporter_id=' . $t_current_user_id . '&amp;show_status=' . $t_bug_resolved_status_threshold,
+					'id' => FILTER_VERIFY
+				);
+
+		}
+
+		if (is_bool($p_filter) || empty($p_filter))
+			return $cache;
+		else if (array_key_exists($p_filter, $cache))
+			return $cache[ $p_filter ];
+		else
+			return false;
+
+	}
+
+	# Returns an array of the default filters for my view
+	function filter_get_default_my_view ( $p_project_id = ALL_PROJECTS ) {
+
+		$t_current_user_id = auth_get_current_user_id();
+
+		# Pull the list of My View boxes per access level
+		$t_access_boxes = config_get( 'my_view_access_boxes' );
+		$t_user_level = access_get_project_level( $p_project_id );
+
+		# If they don't have a custom view by access level, give them the default
+		if (array_key_exists($t_user_level, $t_access_boxes))
+			$t_config_boxes = $t_access_boxes[ $t_user_level ];
+		else
+			$t_config_boxes = config_get( 'my_view_boxes' );
+
+
+		$return = array();
+
+		foreach ($t_config_boxes AS $box) {
+
+			# if box is less than 0, that means it's a predefined box
+			if ($box < 0) {
+				$return[ $box ] = filter_get_predefined( $box );
+			}
+
+			# otherwise, we need to get this filter from the database
+			else {
+				$return[ $box ] = filter_get_row( $box );
+				if (!$return[ $box ])
+					unset ($return[ $box ]);
+				else
+					$return[ $box ]['filter'] = filter_deserialize( $return[ $box ]['filter_string'] );
+			}
+		}
+
+		# don't display "Assigned to Me" bugs to users that bugs can't be assigned to
+		if ( current_user_is_anonymous() || user_get_assigned_open_bug_count( $t_current_user_id, $p_project_id ) == 0 )
+			unset( $return[FILTER_ASSIGNED] );
+
+		# don't display "Monitored by Me" bugs to users that can't monitor bugs
+		if ( current_user_is_anonymous() OR !access_has_project_level( config_get( 'monitor_bug_threshold' ), $p_project_id, $t_current_user_id ) )
+			unset( $return[FILTER_MONITORED] );
+
+
+		# don't display "Reported by Me" bugs to users that can't report bugs
+		if ( current_user_is_anonymous() || !access_has_project_level( config_get( 'report_bug_threshold' ), $p_project_id, $t_current_user_id ) ) {
+			unset( $return[FILTER_REPORTED] );
+			unset( $return[FILTER_FEEDBACK] );
+			unset( $return[FILTER_VERIFY] );
+		}
+
+		return $return;
+	}
+
+	# Returns a list of filters specific to a user for their my_view page
+	function filter_db_get_my_view ( $p_user_id = false ) {
+
+		if (is_bool($p_user_id) || empty($p_user_id))
+			$p_user_id = auth_get_current_user_id();
+
+		$t_filters_my_view_table    = config_get( 'mantis_filters_my_view_table' );
+		$t_filters_table            = config_get( 'mantis_filters_table' );
+
+		$t_user_id = db_prepare_int( $p_user_id );
+
+		$query = "SELECT *
+
+					FROM $t_filters_my_view_table
+					  AS FMV
+
+			   LEFT JOIN $t_filters_table
+					  AS FM
+					  ON FMV.filter_id = FM.id
+
+				   WHERE FMV.user_id = $t_user_id
+					 AND ( "
+
+					 # If the user doesn't have access rights to stored queries, return only predefined filters
+					 .(access_has_project_level( config_get( 'stored_query_use_threshold' ) )?"FM.id IS NOT NULL OR ":"")
+
+					 ." FMV.filter_id < 0 )
+				ORDER BY FMV.sequence ASC";
+
+		$result = db_query( $query );
+		$query_count = db_num_rows( $result );
+
+		if ($query_count <= 0)
+			return array();
+
+		$t_filter_arr = array();
+
+		for ( $i = 0; $i < $query_count; $i++ ) {
+			$row = db_fetch_array( $result );
+
+			# if it is less than 0, that means it is a predefined filter
+			if (intval($row['filter_id']) < 0) {
+				$t_filter_arr[ intval($row['filter_id']) ] = filter_get_predefined( intval($row['filter_id']) );
+			}
+			else {
+				$t_filter_arr[ intval($row['filter_id']) ] = $row;
+				$t_filter_arr[ intval($row['filter_id']) ]['filter'] = filter_deserialize( $row['filter_string'] );
+			}
+
+			// Perform some sequence cleanup
+			if ($row['sequence'] != $i + 1)
+				filter_set_filter_sequence( $i + 1, $row['filter_id'], $t_user_id );
+
+			$t_filter_arr[ intval($row['filter_id']) ]['sequence'] = $i + 1;
+		}
+
+		return $t_filter_arr;
+	}
+
+	# Returns the next sequence value for a user
+	function filter_get_next_sequence ( $p_user_id ) {
+
+		$t_filters_my_view_table    = config_get( 'mantis_filters_my_view_table' );
+		$t_user_id = db_prepare_int( $p_user_id );
+
+		$query = "SELECT MAX(sequence) AS max
+					FROM $t_filters_my_view_table
+				   WHERE user_id = ". $t_user_id;
+
+		$result = db_query($query);
+		$row = db_fetch_array( $result );
+
+		return intval($row['max']) + 1;
+	}
+
+	# Returns boolean whether a filter exists
+	# $p_predefined allows you to set whether or not a predefined filter ID will return true or not
+	function filter_exists ( $p_filter_id, $p_user_id = null, $p_project_id = null, $p_predefined = true) {
+
+		# If less than zero, it must be a predefined filter ID
+		if ($p_filter_id < 0) {
+			if ($p_predefined && filter_get_predefined($p_filter_id))
+				return true;
+			else
+				return false;
+		}
+
+		# I used filter_cache_row instead of filter_get_row so I can control the errors
+		$filter = filter_cache_row( $p_filter_id, false );
+
+		if (!$filter)
+			return false;
+
+		else if (!is_null($p_user_id) && $p_user_id != $filter['user_id'])
+			return false;
+
+		else if (!is_null($p_project_id) && $p_project_id != $filter['project_id'])
+			return false;
+
+		return true;
+	}
+
+	# Removes a filter from a users 'My View'
+	function filter_remove_from_my_view ( $p_filter_id, $p_user_id = null ) {
+
+		if ( empty($p_user_id) || is_bool($p_user_id) )
+			$p_user_id = auth_get_current_user_id();
+
+		$t_filters_my_view_table    = config_get( 'mantis_filters_my_view_table' );
+
+		$c_user_id		= db_prepare_int( $p_user_id );
+		$c_filter_id	= db_prepare_int( $p_filter_id );
+
+		# First, we need to get the sequence of this filter so we can adjust order
+		$query = "SELECT sequence
+					FROM $t_filters_my_view_table
+				   WHERE filter_id = $c_filter_id
+					 AND user_id = $c_user_id
+				   LIMIT 1";
+
+		$result = db_query($query);
+
+		if (db_num_rows( $result ) <= 0)
+			return true;
+
+		$t_sequence = db_fetch_array( $result );
+		$t_sequence = db_prepare_int($t_sequence['sequence']);
+
+		$query = "DELETE FROM $t_filters_my_view_table
+						WHERE filter_id = $c_filter_id
+						  AND user_id = $c_user_id
+						LIMIT 1";
+
+		db_query($query);
+
+		$query = "UPDATE $t_filters_my_view_table
+					 SET sequence = sequence - 1
+				   WHERE sequence > $t_sequence
+					 AND user_id = $c_user_id";
+
+		db_query( $query );
+
+		return true;
+	}
+
+	# adds a new filter to a users 'My View'
+	function filter_add_to_my_view ($p_filter_id, $p_user_id = null) {
+
+		if ( empty($p_user_id) || is_bool($p_user_id) )
+			$p_user_id = auth_get_current_user_id();
+
+		$c_filter_id		= db_prepare_int( $p_filter_id );
+		$c_user_id			= db_prepare_int( $p_user_id );
+
+		# We can't add a non-existent filter
+		if ( !filter_exists( $c_filter_id, $c_user_id ) )
+			return false;
+
+		$t_filters_my_view_table    = config_get( 'mantis_filters_my_view_table' );
+
+		$query = "INSERT INTO $t_filters_my_view_table
+						  SET filter_id = $c_filter_id,
+							  user_id = $c_user_id,
+							  sequence = ". filter_get_next_sequence( $c_user_id );
+
+		db_query( $query );
+
+		return true;
+
+	}
+
+	# updates the sequence for a filter
+	function filter_set_filter_sequence ($p_sequence, $p_filter_id, $p_user_id = null) {
+
+		if ( empty($p_user_id) || is_bool($p_user_id) )
+			$p_user_id = auth_get_current_user_id();
+
+		$c_filter_id		= db_prepare_int( $p_filter_id );
+		$c_user_id			= db_prepare_int( $p_user_id );
+		$c_sequence			= db_prepare_int( $p_sequence );
+
+		$t_filters_my_view_table    = config_get( 'mantis_filters_my_view_table' );
+
+		$query = "UPDATE $t_filters_my_view_table
+					 SET sequence = $c_sequence
+				   WHERE filter_id = $c_filter_id
+					 AND user_id = $c_user_id
+				   LIMIT 1";
+
+		db_query( $query );
+
+	}
+
+	# Prints a select box for adding filters
+	function print_filter_my_view_inactive ( $p_show_empty = true ) {
+
+		$p_user_id = auth_get_current_user_id();
+
+		# Get the filters the user currently displays on their My View
+		$t_active = array_keys( filter_db_get_my_view() );
+
+		# Get all the predefined filters, then weed out the ones they have already set
+		$t_predefined = filter_get_predefined();
+		foreach ($t_predefined AS $key => $filter) {
+			if (in_array($key, $t_active))
+				unset($t_predefined[$key]);
+			else
+				$t_predefined[ $key ] = $filter['name'];
+		}
+
+		if ( access_has_project_level( config_get( 'stored_query_use_threshold' ) ) ) {
+
+			# Get all the available filters, then weed out the ones already in use
+			$t_available = filter_db_get_available_queries( ALL_PROJECTS, $p_user_id );
+			foreach ($t_available AS $key => $filter) {
+				if (in_array($key, $t_active))
+					unset($t_available[$key]);
+			}
+
+		} else {
+			$t_available = array();
+		}
+
+		# If both lists are empty, don't show the form unless they want us to
+		if (count($t_predefined) <= 0 && count($t_available) <= 0 && !$p_show_empty)
+			return;
+
+		?>
+		<form action="account_my_view_add.php" method="post">
+		<select name="filter_id">
+			<?php
+
+			if (count($t_available) > 0) {
+				echo "<optgroup label='". lang_get('custom_filters') ."'>";
+
+				foreach ($t_available AS $f_key => $f_title) {
+					echo "<option value='". $f_key ."'>" . string_display_line($f_title) . "</option>";
+				}
+				echo "</optgroup>";
+			}
+
+			if (count($t_predefined) > 0) {
+				echo "<optgroup label='". lang_get('predefined_filters') ."'>";
+
+				foreach ($t_predefined AS $f_key => $f_title) {
+					echo "<option value='". $f_key ."'>". string_display_line($f_title) ."</option>";
+				}
+				echo "</optgroup>";
+			}
+
+			?>
+		</select>
+		<input type="submit" class="button" value="<?php echo lang_get('add_my_view_filter'); ?>" />
+		</form>
+		<?php
+	}
+
+	# Prints a my view box from a set of query results
+	function print_filter_my_view_box ( $p_title, $p_page_number, $p_per_page, $p_custom_filter,
+										$p_project_id, $p_user_id, $p_show_sticky = null, $p_url = null, $p_show_empty = TRUE ) {
+
+		$t_page_count = 0;
+		$t_bug_count = 0;
+
+		# Run the filter query
+		$result = filter_get_bug_rows( $p_page_number, $p_per_page, $t_page_count, $t_bug_count,
+									$p_custom_filter, $p_project_id, $p_user_id, $p_show_sticky );
+
+		if (count($result) == 0 && !$p_show_empty)
+			return;
+
+		if (is_null($p_url))
+			$p_url = filter_get_url( $p_custom_filter );
+
+		$t_icon_path = config_get( 'icon_path' );
+		$t_update_bug_threshold = config_get( 'update_bug_threshold' );
+
+		?>
+		<table class="width100" cellspacing="1">
+			<tr>
+				<td class="form-title" colspan="2">
+					<a class="subtle" href="<?php echo $p_url; ?>"><?php echo string_display_line($p_title); ?></a>
+					[<a class="subtle" href="<?php echo $p_url; ?>" target="_blank">^</a>]
+					( <?php echo string_display_line(project_get_name( $p_project_id )); ?> )
+					<?php
+						if ( count( $result ) > 0 ) {
+							$v_start = $p_per_page * ($p_page_number - 1) + 1;
+							$v_end   = $v_start + count( $result ) - 1;
+						} else {
+							$v_start = 0;
+							$v_end   = 0;
+						}
+						echo "($v_start - $v_end / $t_bug_count)";
+					?>
+				</td>
+			</tr>
+			<?php
+			foreach ($result AS $row) {
+
+				?>
+				<tr bgcolor="<?php echo get_status_color($row['status']) ?>">
+
+					<td class="center">
+						<span class="small">
+						<?php
+							print_bug_link( $row['id'] );
+
+							echo '<br />';
+
+							if ( !bug_is_readonly( $row['id'] ) && access_has_bug_level( $t_update_bug_threshold, $row['id'] ) ) {
+								echo '<a href="' . string_get_bug_update_url( $row['id'] ) . '"><img border="0" src="' . $t_icon_path . 'update.png' . '" alt="' . lang_get( 'update_bug_button' ) . '" /></a>';
+							}
+
+							if ( ON == config_get( 'show_priority_text' ) ) {
+								print_formatted_priority_string( $row['status'], $row['priority'] );
+							} else {
+								print_status_icon( $row['priority'] );
+							}
+
+							$t_attachment_count = 0;
+							if (  ( file_can_view_bug_attachments( $row['id'] ) ) ) {
+							   $t_attachment_count = file_bug_attachment_count( $row['id'] );
+							}
+
+							if ( 0 < $t_attachment_count ) {
+								echo '<a href="' . string_get_bug_view_url( $row['id'] ) . '#attachments">';
+								echo '<img border="0" src="' . $t_icon_path . 'attachment.png' . '"';
+								echo ' alt="' . lang_get( 'attachment_alt' ) . '"';
+								echo ' title="' . $t_attachment_count . ' ' . lang_get( 'attachments' ) . '"';
+								echo ' />';
+								echo '</a>';
+							}
+							if ( VS_PRIVATE == $row['view_state'] ) {
+								echo '<img src="' . $t_icon_path . 'protected.gif" width="8" height="15" alt="' . lang_get( 'private' ) . '" />';
+							}
+						?>
+						</span>
+					</td>
+					<td class="left" valign="top" width="100%">
+						<span class="small">
+						<?php
+
+							echo string_attribute( $row['summary'] )
+								.'<br />';
+							# show project name if viewing 'all projects' or bug is in subproject
+							if ( ON == config_get( 'show_bug_project_links' ) &&
+								helper_get_current_project() != $row['project_id'] ) {
+								echo '['. project_get_name($row['project_id']) .'] ';
+							}
+
+							echo string_display( $row['category'] );
+
+							$t_last_updated = date( config_get( 'normal_date_format' ), $row['last_updated'] );
+
+							if ( $row['last_updated'] > strtotime( '-'. $p_custom_filter['highlight_changed'] .' hours' ) ) {
+								echo ' - <b>' . $t_last_updated . '</b>';
+							} else {
+								echo ' - ' . $t_last_updated;
+							}
+
+						?>
+						</span>
+					</td>
+				</tr>
+				<?php
+			}
+			?>
+		</table>
+
+		<?
+
+	}
+
+
 
 	/**
 	 * The following functions each print out an individual filter field.
Index: core/html_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/html_api.php,v
retrieving revision 1.219
diff -u -b -r1.219 html_api.php
--- core/html_api.php	22 Oct 2007 07:05:45 -0000	1.219
+++ core/html_api.php	23 Oct 2007 19:23:21 -0000
@@ -750,18 +750,25 @@
 	function print_account_menu( $p_page='' ) {
 		$t_account_page 				= 'account_page.php';
 		$t_account_prefs_page 			= 'account_prefs_page.php';
+		$t_account_my_view_page 		= 'account_my_view_page.php';
 		$t_account_profile_menu_page 	= 'account_prof_menu_page.php';
 		$t_account_sponsor_page			= 'account_sponsor_page.php';
 
 		switch ( $p_page ) {
 			case $t_account_page				: $t_account_page 				= ''; break;
 			case $t_account_prefs_page			: $t_account_prefs_page 		= ''; break;
+			case $t_account_my_view_page		: $t_account_my_view_page 		= ''; break;
 			case $t_account_profile_menu_page	: $t_account_profile_menu_page 	= ''; break;
 			case $t_account_sponsor_page		: $t_account_sponsor_page		= ''; break;
 		}
 
 		print_bracket_link( $t_account_page, lang_get( 'account_link' ) );
 		print_bracket_link( $t_account_prefs_page, lang_get( 'change_preferences_link' ) );
+
+
+		if (access_has_global_level(config_get('custom_my_view_threshold')))
+			print_bracket_link( $t_account_my_view_page, lang_get( 'my_view_link' ) );
+
 		if ( access_has_project_level( config_get( 'add_profile_threshold' ) ) ) {
 			print_bracket_link( $t_account_profile_menu_page, lang_get( 'manage_profiles_link' ) );
 		}
Index: lang/strings_english.txt
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/lang/strings_english.txt,v
retrieving revision 1.316
diff -u -b -r1.316 strings_english.txt
--- lang/strings_english.txt	22 Sep 2007 22:51:15 -0000	1.316
+++ lang/strings_english.txt	23 Oct 2007 19:23:21 -0000
@@ -1432,4 +1432,10 @@
 $s_graph_page = 'Graph Bug History';
 $s_graph_bug_page_link = 'Graph';
 
+# Custom Filtering
+$s_add_my_view_filter = 'Add Filter to My View';
+$s_my_view_filters = 'My View Filters';
+$s_predefined_filters = 'Predefined Filters';
+$s_custom_filters = 'Custom Filters';
+
 ?>
customMyView_v2.diff (33,697 bytes)
Nycto

Nycto

2007-10-23 15:42

reporter   ~0015960

re-uploaded

giallu

giallu

2007-10-24 05:10

reporter   ~0015969

I am interested in this feature, so If no one beats me on that, I will happily review/commit your code.

ghohm

ghohm

2008-03-05 06:20

reporter   ~0017258

Do you think this customization work with the last version 1.1.1?

If, yes, why didn't you add this very useful feature in the last Mantis' version?

Gôm

2008-03-05 08:19

 

mantis1.GIF (10,669 bytes)
mantis1.GIF (10,669 bytes)
mauro

mauro

2008-03-05 08:22

reporter   ~0017260

Last edited: 2008-03-05 08:23

I install this improve but account_my_view_page.php and my_view_page.php are empty.I don't know how I can complete data, any idea?
I attach image example.

thanks

ghohm

ghohm

2008-03-05 11:22

reporter   ~0017261

Someone know how can I execute this command (see "readme")?

3) Apply the diff file with the following command:
patch -p0 < customMyView.diff

Yes ... My Mantis is working on Windows!

mkornatzki

mkornatzki

2008-03-07 17:30

reporter   ~0017286

this feature is great.
thanks for the development.

there is only one error. If a user wants to add a custom filter add by another one the page refreshes but the filter didn't append.

you can fix this if you edit the function filter_add_to_my_view in filter api as follows:

change if ( !filter_exists( $c_filter_id, $c_user_id ) )
to if ( !filter_exists( $c_filter_id, null ) )

mauro

mauro

2008-03-10 05:18

reporter   ~0017304

I change
if ( !filter_exists( $c_filter_id, $c_user_id ) )to
if ( !filter_exists( $c_filter_id, null ) )

but in "My View" the custom filters don't appear.
The process that i follow is:
1 - Go to "View Issues" and create a new filter and save it.
2 - Go to "My Account" and Custom Filters are empty.

Another idea.....
Thanks

2008-05-31 16:13

 

configurable_my_view.patch (34,142 bytes)
Index: config_defaults_inc.php
===================================================================
--- config_defaults_inc.php	(revision 5305)
+++ config_defaults_inc.php	(working copy)
@@ -1427,6 +1427,7 @@
 	$g_db_table['mantis_custom_field_string_table']    = '%db_table_prefix%_custom_field_string%db_table_suffix%';
 	$g_db_table['mantis_upgrade_table']					= '%db_table_prefix%_upgrade%db_table_suffix%';
 	$g_db_table['mantis_filters_table']					= '%db_table_prefix%_filters%db_table_suffix%';
+	$g_db_table['mantis_filters_my_view_table']	= '%db_table_prefix%_filters_my_view%db_table_suffix%';
 	$g_db_table['mantis_sponsorship_table']				= '%db_table_prefix%_sponsorship%db_table_suffix%';
 	$g_db_table['mantis_tokens_table']					= '%db_table_prefix%_tokens%db_table_suffix%';
 	$g_db_table['mantis_project_hierarchy_table']		= '%db_table_prefix%_project_hierarchy%db_table_suffix%';
@@ -1756,20 +1757,42 @@
 	# Boxes to be shown and their order
 	# A box that is not to be shown can have its value set to 0
 	$g_my_view_boxes = array (
-		'assigned'      => '1',
-		'unassigned'    => '2',
-		'reported'      => '3',
-		'resolved'      => '4',
-		'recent_mod'	=> '5',
-		'monitored'		=> '6',
-		'feedback'		=> '0',
-		'verify'		=> '0'
+		FILTER_ASSIGNED,
+		FILTER_UNASSIGNED,
+		FILTER_REPORTED,
+		FILTER_RESOLVED,
+		FILTER_RECENT_MOD,
+		FILTER_MONITORED,
+		// FILTER_FEEDBACK,
+		// FILTER_VERIFY,
 	);
 
+	# Allows you to set a custom "My View" on an access level basis
+	# To do this, set the key of the first dimension to the access level, then
+	# make the value an array of filters. For example:
+	# $g_my_view_access_boxes = array (
+	# 	ADMINISTRATOR => array(
+	#		FILTER_UNASSIGNED,
+	#		FILTER_ASSIGNED
+	#	),
+	#   REPORTER => array(
+	#		FILTER_REPORTED,
+	#		FILTER_MONITORED
+	#	)
+	# );
+	$g_my_view_access_boxes = array (
+ 	);
+
+	# threshold needed to customize the 'My View' screen
+	$g_custom_my_view_threshold = ANYBODY;
+ 	
 	# Toggle whether 'My View' boxes are shown in a fixed position (i.e. adjacent boxes start at the same vertical position)
 	$g_my_view_boxes_fixed_position = ON;
 
+	# Toggle whether 'My View' boxes are shown in a fixed position (i.e. adjacent boxes start at the same vertical position)
+	$g_my_view_boxes_fixed_position = ON;
 
+
 	######################
 	# RSS Feeds
 	######################
Index: core/constant_inc.php
===================================================================
--- core/constant_inc.php	(revision 5305)
+++ core/constant_inc.php	(working copy)
@@ -354,6 +354,16 @@
 	define( 'FILTER_POSITION_BOTTOM',			2 );
 	define( 'FILTER_POSITION_BOTH',				3 );  // FILTER_POSITION_TOP | FILTER_POSITION_BOTTOM (bitwise OR)
 
+	# Default Filters
+	define( 'FILTER_ASSIGNED',					-1 );
+	define( 'FILTER_RECENT_MOD',				-2 );
+	define( 'FILTER_REPORTED',					-3 );
+	define( 'FILTER_RESOLVED',					-4 );
+	define( 'FILTER_UNASSIGNED',				-5 );
+	define( 'FILTER_MONITORED',					-6 );
+	define( 'FILTER_FEEDBACK',					-7 );
+	define( 'FILTER_VERIFY',					-8 );
+
 	# Flags for settings E-mail categories
 	define( 'EMAIL_CATEGORY_PROJECT_CATEGORY',	1);
 
Index: core/filter_api.php
===================================================================
--- core/filter_api.php	(revision 5305)
+++ core/filter_api.php	(working copy)
@@ -3371,8 +3371,612 @@
 		# all of our filter values are now guaranteed to be there, and correct.
 		return $p_filter_arr;
 	}
+	
+	# Returns an array of the pre-defined filters
+	function filter_get_predefined ( $p_filter = false ) {
+		static $cache;
 
+		if (!isset($cache)) {
 
+			$t_bug_resolved_status_threshold = config_get( 'bug_resolved_status_threshold' );
+			$t_hide_status_default = config_get( 'hide_status_default' );
+			$t_default_show_changed = config_get( 'default_show_changed' );
+			$t_current_user_id = auth_get_current_user_id();
+
+			$cache = array();
+
+			$cache[ FILTER_ASSIGNED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => $t_current_user_id ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_bug_resolved_status_threshold ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_assigned' ),
+					'url' => 'handler_id=' . $t_current_user_id . '&amp;hide_status=' . $t_bug_resolved_status_threshold,
+					'id' => FILTER_ASSIGNED
+				);
+
+			$cache[ FILTER_RECENT_MOD ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => META_FILTER_NONE ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_recent_mod' ),
+					'url' => 'hide_status=none',
+					'id' => FILTER_RECENT_MOD
+				);
+
+			$cache[ FILTER_REPORTED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => $t_current_user_id ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'sort'			=> 'last_updated',
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_reported' ),
+					'url' => 'reporter_id=' . $t_current_user_id . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_REPORTED
+				);
+
+			$cache[ FILTER_RESOLVED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => $t_bug_resolved_status_threshold ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_resolved' ),
+					'url' => 'show_status=' . $t_bug_resolved_status_threshold . '&amp;hide_status=' . $t_bug_resolved_status_threshold,
+					'id' => FILTER_RESOLVED
+				);
+
+			$cache[ FILTER_UNASSIGNED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_NONE ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_unassigned' ),
+					'url' => 'handler_id=[none]' . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_UNASSIGNED
+				);
+
+			$cache[ FILTER_MONITORED ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => META_FILTER_ANY ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => $t_current_user_id )
+						),
+					'name' => lang_get( 'my_view_title_monitored' ),
+					'url' => 'user_monitor=' . $t_current_user_id . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_MONITORED
+				);
+
+
+			$cache[ FILTER_FEEDBACK ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => FEEDBACK ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => $t_current_user_id ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_feedback' ),
+					'url' => 'reporter_id=' . $t_current_user_id . '&amp;show_status=' . FEEDBACK . '&amp;hide_status=' . $t_hide_status_default,
+					'id' => FILTER_FEEDBACK
+				);
+
+			$cache[ FILTER_VERIFY ] = array(
+					'filter' => array(
+							'show_category'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_severity'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_status'		=> Array ( '0' => $t_bug_resolved_status_threshold ),
+							'highlight_changed'	=> $t_default_show_changed,
+							'reporter_id'		=> Array ( '0' => $t_current_user_id ),
+							'handler_id'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_resolution'	=> Array ( '0' => META_FILTER_ANY ),
+							'show_build'		=> Array ( '0' => META_FILTER_ANY ),
+							'show_version'		=> Array ( '0' => META_FILTER_ANY ),
+							'hide_status'		=> Array ( '0' => $t_hide_status_default ),
+							'user_monitor'		=> Array ( '0' => META_FILTER_ANY )
+						),
+					'name' => lang_get( 'my_view_title_verify' ),
+					'url' => 'reporter_id=' . $t_current_user_id . '&amp;show_status=' . $t_bug_resolved_status_threshold,
+					'id' => FILTER_VERIFY
+				);
+
+		}
+
+		if (is_bool($p_filter) || empty($p_filter))
+			return $cache;
+		else if (array_key_exists($p_filter, $cache))
+			return $cache[ $p_filter ];
+		else
+			return false;
+
+	}
+
+	# Returns an array of the default filters for my view
+	function filter_get_default_my_view ( $p_project_id = ALL_PROJECTS ) {
+
+		$t_current_user_id = auth_get_current_user_id();
+
+		# Pull the list of My View boxes per access level
+		$t_access_boxes = config_get( 'my_view_access_boxes' );
+		$t_user_level = access_get_project_level( $p_project_id );
+
+		# If they don't have a custom view by access level, give them the default
+		if (array_key_exists($t_user_level, $t_access_boxes))
+			$t_config_boxes = $t_access_boxes[ $t_user_level ];
+		else
+			$t_config_boxes = config_get( 'my_view_boxes' );
+
+
+		$return = array();
+
+		foreach ($t_config_boxes AS $box) {
+
+			# if box is less than 0, that means it's a predefined box
+			if ($box < 0) {
+				$return[ $box ] = filter_get_predefined( $box );
+			}
+
+			# otherwise, we need to get this filter from the database
+			else {
+				$return[ $box ] = filter_get_row( $box );
+				if (!$return[ $box ])
+					unset ($return[ $box ]);
+				else
+					$return[ $box ]['filter'] = filter_deserialize( $return[ $box ]['filter_string'] );
+			}
+		}
+
+		# don't display "Assigned to Me" bugs to users that bugs can't be assigned to
+		if ( current_user_is_anonymous() || user_get_assigned_open_bug_count( $t_current_user_id, $p_project_id ) == 0 )
+			unset( $return[FILTER_ASSIGNED] );
+
+		# don't display "Monitored by Me" bugs to users that can't monitor bugs
+		if ( current_user_is_anonymous() OR !access_has_project_level( config_get( 'monitor_bug_threshold' ), $p_project_id, $t_current_user_id ) )
+			unset( $return[FILTER_MONITORED] );
+
+
+		# don't display "Reported by Me" bugs to users that can't report bugs
+		if ( current_user_is_anonymous() || !access_has_project_level( config_get( 'report_bug_threshold' ), $p_project_id, $t_current_user_id ) ) {
+			unset( $return[FILTER_REPORTED] );
+			unset( $return[FILTER_FEEDBACK] );
+			unset( $return[FILTER_VERIFY] );
+		}
+
+		return $return;
+	}
+
+	# Returns a list of filters specific to a user for their my_view page
+	function filter_db_get_my_view ( $p_user_id = false ) {
+
+		if (is_bool($p_user_id) || empty($p_user_id))
+			$p_user_id = auth_get_current_user_id();
+
+		$t_filters_my_view_table    = db_get_table( 'mantis_filters_my_view_table' );
+		$t_filters_table            = db_get_table( 'mantis_filters_table' );
+
+		$t_user_id = db_prepare_int( $p_user_id );
+
+		$query = "SELECT *
+
+					FROM $t_filters_my_view_table
+					  AS FMV
+
+			   LEFT JOIN $t_filters_table
+					  AS FM
+					  ON FMV.filter_id = FM.id
+
+				   WHERE FMV.user_id = $t_user_id
+					 AND ( "
+
+					 # If the user doesn't have access rights to stored queries, return only predefined filters
+					 .(access_has_project_level( config_get( 'stored_query_use_threshold' ) )?"FM.id IS NOT NULL OR ":"")
+
+					 ." FMV.filter_id < 0 )
+				ORDER BY FMV.sequence ASC";
+
+		$result = db_query( $query );
+		$query_count = db_num_rows( $result );
+
+		if ($query_count <= 0)
+			return array();
+
+		$t_filter_arr = array();
+
+		for ( $i = 0; $i < $query_count; $i++ ) {
+			$row = db_fetch_array( $result );
+
+			# if it is less than 0, that means it is a predefined filter
+			if (intval($row['filter_id']) < 0) {
+				$t_filter_arr[ intval($row['filter_id']) ] = filter_get_predefined( intval($row['filter_id']) );
+			}
+			else {
+				$t_filter_arr[ intval($row['filter_id']) ] = $row;
+				$t_filter_arr[ intval($row['filter_id']) ]['filter'] = filter_deserialize( $row['filter_string'] );
+			}
+
+			// Perform some sequence cleanup
+			if ($row['sequence'] != $i + 1)
+				filter_set_filter_sequence( $i + 1, $row['filter_id'], $t_user_id );
+
+			$t_filter_arr[ intval($row['filter_id']) ]['sequence'] = $i + 1;
+		}
+
+		return $t_filter_arr;
+	}
+
+	# Returns the next sequence value for a user
+	function filter_get_next_sequence ( $p_user_id ) {
+
+		$t_filters_my_view_table    = db_get_table( 'mantis_filters_my_view_table' );
+		$t_user_id = db_prepare_int( $p_user_id );
+
+		$query = "SELECT MAX(sequence) AS max
+					FROM $t_filters_my_view_table
+				   WHERE user_id = ". $t_user_id;
+
+		$result = db_query($query);
+		$row = db_fetch_array( $result );
+
+		return intval($row['max']) + 1;
+	}
+
+	# Returns boolean whether a filter exists
+	# $p_predefined allows you to set whether or not a predefined filter ID will return true or not
+	function filter_exists ( $p_filter_id, $p_user_id = null, $p_project_id = null, $p_predefined = true) {
+
+		# If less than zero, it must be a predefined filter ID
+		if ($p_filter_id < 0) {
+			if ($p_predefined && filter_get_predefined($p_filter_id))
+				return true;
+			else
+				return false;
+		}
+
+		# I used filter_cache_row instead of filter_get_row so I can control the errors
+		$filter = filter_cache_row( $p_filter_id, false );
+
+		if (!$filter)
+			return false;
+
+		else if (!is_null($p_user_id) && $p_user_id != $filter['user_id'])
+			return false;
+
+		else if (!is_null($p_project_id) && $p_project_id != $filter['project_id'])
+			return false;
+
+		return true;
+	}
+
+	# Removes a filter from a users 'My View'
+	function filter_remove_from_my_view ( $p_filter_id, $p_user_id = null ) {
+
+		if ( empty($p_user_id) || is_bool($p_user_id) )
+			$p_user_id = auth_get_current_user_id();
+
+		$t_filters_my_view_table    = db_get_table( 'mantis_filters_my_view_table' );
+
+		$c_user_id		= db_prepare_int( $p_user_id );
+		$c_filter_id	= db_prepare_int( $p_filter_id );
+
+		# First, we need to get the sequence of this filter so we can adjust order
+		$query = "SELECT sequence
+					FROM $t_filters_my_view_table
+				   WHERE filter_id = $c_filter_id
+					 AND user_id = $c_user_id
+				   LIMIT 1";
+
+		$result = db_query($query);
+
+		if (db_num_rows( $result ) <= 0)
+			return true;
+
+		$t_sequence = db_fetch_array( $result );
+		$t_sequence = db_prepare_int($t_sequence['sequence']);
+
+		$query = "DELETE FROM $t_filters_my_view_table
+						WHERE filter_id = $c_filter_id
+						  AND user_id = $c_user_id
+						LIMIT 1";
+
+		db_query($query);
+
+		$query = "UPDATE $t_filters_my_view_table
+					 SET sequence = sequence - 1
+				   WHERE sequence > $t_sequence
+					 AND user_id = $c_user_id";
+
+		db_query( $query );
+
+		return true;
+	}
+
+	# adds a new filter to a users 'My View'
+	function filter_add_to_my_view ($p_filter_id, $p_user_id = null) {
+
+		if ( empty($p_user_id) || is_bool($p_user_id) )
+			$p_user_id = auth_get_current_user_id();
+
+		$c_filter_id		= db_prepare_int( $p_filter_id );
+		$c_user_id			= db_prepare_int( $p_user_id );
+
+		# We can't add a non-existent filter
+		if ( !filter_exists( $c_filter_id, $c_user_id ) )
+			return false;
+
+		$t_filters_my_view_table    = db_get_table( 'mantis_filters_my_view_table' );
+
+		$query = "INSERT INTO $t_filters_my_view_table
+						  SET filter_id = $c_filter_id,
+							  user_id = $c_user_id,
+							  sequence = ". filter_get_next_sequence( $c_user_id );
+
+		db_query( $query );
+
+		return true;
+
+	}
+
+	# updates the sequence for a filter
+	function filter_set_filter_sequence ($p_sequence, $p_filter_id, $p_user_id = null) {
+
+		if ( empty($p_user_id) || is_bool($p_user_id) )
+			$p_user_id = auth_get_current_user_id();
+
+		$c_filter_id		= db_prepare_int( $p_filter_id );
+		$c_user_id			= db_prepare_int( $p_user_id );
+		$c_sequence			= db_prepare_int( $p_sequence );
+
+		$t_filters_my_view_table    = db_get_table( 'mantis_filters_my_view_table' );
+
+		$query = "UPDATE $t_filters_my_view_table
+					 SET sequence = $c_sequence
+				   WHERE filter_id = $c_filter_id
+					 AND user_id = $c_user_id
+				   LIMIT 1";
+
+		db_query( $query );
+
+	}
+
+	# Prints a select box for adding filters
+	function print_filter_my_view_inactive ( $p_show_empty = true ) {
+
+		$p_user_id = auth_get_current_user_id();
+
+		# Get the filters the user currently displays on their My View
+		$t_active = array_keys( filter_db_get_my_view() );
+
+		# Get all the predefined filters, then weed out the ones they have already set
+		$t_predefined = filter_get_predefined();
+		foreach ($t_predefined AS $key => $filter) {
+			if (in_array($key, $t_active))
+				unset($t_predefined[$key]);
+			else
+				$t_predefined[ $key ] = $filter['name'];
+		}
+
+		if ( access_has_project_level( config_get( 'stored_query_use_threshold' ) ) ) {
+
+			# Get all the available filters, then weed out the ones already in use
+			$t_available = filter_db_get_available_queries( ALL_PROJECTS, $p_user_id );
+			foreach ($t_available AS $key => $filter) {
+				if (in_array($key, $t_active))
+					unset($t_available[$key]);
+			}
+
+		} else {
+			$t_available = array();
+		}
+
+		# If both lists are empty, don't show the form unless they want us to
+		if (count($t_predefined) <= 0 && count($t_available) <= 0 && !$p_show_empty)
+			return;
+
+		?>
+		<form action="account_my_view_add.php" method="post">
+		<select name="filter_id">
+			<?php
+
+			if (count($t_available) > 0) {
+				echo "<optgroup label='". lang_get('custom_filters') ."'>";
+
+				foreach ($t_available AS $f_key => $f_title) {
+					echo "<option value='". $f_key ."'>" . string_display_line($f_title) . "</option>";
+				}
+				echo "</optgroup>";
+			}
+
+			if (count($t_predefined) > 0) {
+				echo "<optgroup label='". lang_get('predefined_filters') ."'>";
+
+				foreach ($t_predefined AS $f_key => $f_title) {
+					echo "<option value='". $f_key ."'>". string_display_line($f_title) ."</option>";
+				}
+				echo "</optgroup>";
+			}
+
+			?>
+		</select>
+		<input type="submit" class="button" value="<?php echo lang_get('add_my_view_filter'); ?>" />
+		</form>
+		<?php
+	}
+
+	# Prints a my view box from a set of query results
+	function print_filter_my_view_box ( $p_title, $p_page_number, $p_per_page, $p_custom_filter,
+										$p_project_id, $p_user_id, $p_show_sticky = null, $p_url = null, $p_show_empty = TRUE ) {
+
+		$t_page_count = 0;
+		$t_bug_count = 0;
+
+		# Run the filter query
+		$result = filter_get_bug_rows( $p_page_number, $p_per_page, $t_page_count, $t_bug_count,
+									$p_custom_filter, $p_project_id, $p_user_id, $p_show_sticky );
+
+		if (count($result) == 0 && !$p_show_empty)
+			return;
+
+		if (is_null($p_url))
+			$p_url = filter_get_url( $p_custom_filter );
+
+		$t_icon_path = config_get( 'icon_path' );
+		$t_update_bug_threshold = config_get( 'update_bug_threshold' );
+
+		?>
+		<table class="width100" cellspacing="1">
+			<tr>
+				<td class="form-title" colspan="2">
+					<a class="subtle" href="<?php echo $p_url; ?>"><?php echo string_display_line($p_title); ?></a>
+					[<a class="subtle" href="<?php echo $p_url; ?>" target="_blank">^</a>]
+					( <?php echo string_display_line(project_get_name( $p_project_id )); ?> )
+					<?php
+						if ( count( $result ) > 0 ) {
+							$v_start = $p_per_page * ($p_page_number - 1) + 1;
+							$v_end   = $v_start + count( $result ) - 1;
+						} else {
+							$v_start = 0;
+							$v_end   = 0;
+						}
+						echo "($v_start - $v_end / $t_bug_count)";
+					?>
+				</td>
+			</tr>
+			<?php
+			foreach ($result AS $row) {
+
+				?>
+				<tr bgcolor="<?php echo get_status_color($row['status']) ?>">
+
+					<td class="center">
+						<span class="small">
+						<?php
+							print_bug_link( $row['id'] );
+
+							echo '<br />';
+
+							if ( !bug_is_readonly( $row['id'] ) && access_has_bug_level( $t_update_bug_threshold, $row['id'] ) ) {
+								echo '<a href="' . string_get_bug_update_url( $row['id'] ) . '"><img border="0" src="' . $t_icon_path . 'update.png' . '" alt="' . lang_get( 'update_bug_button' ) . '" /></a>';
+							}
+
+							if ( ON == config_get( 'show_priority_text' ) ) {
+								print_formatted_priority_string( $row['status'], $row['priority'] );
+							} else {
+								print_status_icon( $row['priority'] );
+							}
+
+							$t_attachment_count = 0;
+							if (  ( file_can_view_bug_attachments( $row['id'] ) ) ) {
+							   $t_attachment_count = file_bug_attachment_count( $row['id'] );
+							}
+
+							if ( 0 < $t_attachment_count ) {
+								echo '<a href="' . string_get_bug_view_url( $row['id'] ) . '#attachments">';
+								echo '<img border="0" src="' . $t_icon_path . 'attachment.png' . '"';
+								echo ' alt="' . lang_get( 'attachment_alt' ) . '"';
+								echo ' title="' . $t_attachment_count . ' ' . lang_get( 'attachments' ) . '"';
+								echo ' />';
+								echo '</a>';
+							}
+							if ( VS_PRIVATE == $row['view_state'] ) {
+								echo '<img src="' . $t_icon_path . 'protected.gif" width="8" height="15" alt="' . lang_get( 'private' ) . '" />';
+							}
+						?>
+						</span>
+					</td>
+					<td class="left" valign="top" width="100%">
+						<span class="small">
+						<?php
+
+							echo string_attribute( $row['summary'] )
+								.'<br />';
+							# show project name if viewing 'all projects' or bug is in subproject
+							if ( ON == config_get( 'show_bug_project_links' ) &&
+								helper_get_current_project() != $row['project_id'] ) {
+								echo '['. project_get_name($row['project_id']) .'] ';
+							}
+
+							echo string_display( $row['category'] );
+
+							$t_last_updated = date( config_get( 'normal_date_format' ), $row['last_updated'] );
+
+							if ( $row['last_updated'] > strtotime( '-'. $p_custom_filter['highlight_changed'] .' hours' ) ) {
+								echo ' - <b>' . $t_last_updated . '</b>';
+							} else {
+								echo ' - ' . $t_last_updated;
+							}
+
+						?>
+						</span>
+					</td>
+				</tr>
+				<?php
+			}
+			?>
+		</table>
+
+		<?
+
+	}
+
 	/**
 	 * The following functions each print out an individual filter field.
 	 * They are derived from view_filters_page.php
Index: core/html_api.php
===================================================================
--- core/html_api.php	(revision 5305)
+++ core/html_api.php	(working copy)
@@ -841,6 +841,7 @@
 	function print_account_menu( $p_page='' ) {
 		$t_account_page 				= 'account_page.php';
 		$t_account_prefs_page 			= 'account_prefs_page.php';
+		$t_account_my_view_page 		= 'account_my_view_page.php';
 		$t_account_profile_menu_page 	= 'account_prof_menu_page.php';
 		$t_account_sponsor_page			= 'account_sponsor_page.php';
 		$t_account_manage_columns_page	= 'account_manage_columns_page.php';
@@ -852,6 +853,9 @@
 			case $t_account_prefs_page:
 				$t_account_prefs_page = '';
 				break;
+			case $t_account_my_view_page: 
+				$t_account_my_view_page = ''; 
+				break;				
 			case $t_account_profile_menu_page:
 				$t_account_profile_menu_page 	= '';
 				break;
@@ -865,6 +869,8 @@
 
 		print_bracket_link( $t_account_page, lang_get( 'account_link' ) );
 		print_bracket_link( $t_account_prefs_page, lang_get( 'change_preferences_link' ) );
+		if (access_has_global_level(config_get('custom_my_view_threshold')))
+			print_bracket_link( $t_account_my_view_page, lang_get( 'my_view_link' ) );
 		print_bracket_link( $t_account_manage_columns_page, lang_get( 'manage_columns_config' ) );
 
 		if ( access_has_project_level( config_get( 'add_profile_threshold' ) ) ) {
Index: lang/strings_english.txt
===================================================================
--- lang/strings_english.txt	(revision 5305)
+++ lang/strings_english.txt	(working copy)
@@ -1528,4 +1528,9 @@
 #account_view_page.php
 $s_view_account_title = 'User Information';
 
+# Custom Filtering
+$s_add_my_view_filter = 'Add Filter to My View';
+$s_my_view_filters = 'My View Filters';
+$s_predefined_filters = 'Predefined Filters';
+$s_custom_filters = 'Custom Filters';
 ?>
Index: my_view_page.php
===================================================================
--- my_view_page.php	(revision 5305)
+++ my_view_page.php	(working copy)
@@ -29,6 +29,7 @@
 	require_once( $t_core_path . 'compress_api.php' );
 	require_once( $t_core_path . 'filter_api.php' );
 	require_once( $t_core_path . 'last_visited_api.php' );
+	require_once( $t_core_path . 'icon_api.php' );
 
 	auth_ensure_user_authenticated();
 
@@ -55,11 +56,6 @@
 	$t_bug_count = null;
 	$t_page_count = null;
 
-	$t_boxes = config_get( 'my_view_boxes' );
-	asort ($t_boxes);
-	reset ($t_boxes);
-	#print_r ($t_boxes);
-
 	$t_project_id = helper_get_current_project();
 ?>
 
@@ -79,88 +75,115 @@
 ?>
 
 <?php
-	$t_number_of_boxes = count ( $t_boxes );
 	$t_boxes_position = config_get( 'my_view_boxes_fixed_position' );
+	$t_custom_my_view_threshold = config_get('custom_my_view_threshold');
+
+	# Make sure they have access to define a custom 'my view'
+	if (access_has_global_level($t_custom_my_view_threshold)) {
+		# Get the list of custom my_view filters
+		$t_filters = filter_db_get_my_view( $t_current_user_id, TRUE );
+
+		# If they set no custom filters, then get the default view
+		if (count($t_filters) <= 0)
+			$t_filters = filter_get_default_my_view( $t_project_id );
+
+	}	else {
+		$t_filters = filter_get_default_my_view( $t_project_id );
+	}
+
+	$t_number_of_boxes = count($t_filters);
+
 	$t_counter = 0;
 
-	while (list ($t_box_title, $t_box_display) = each ($t_boxes)) {
-		# don't display bugs that are set as 0
-		if ($t_box_display == 0) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+	foreach ($t_filters AS $filter) {
+		$t_counter++;
 
-		# don't display "Assigned to Me" bugs to users that bugs can't be assigned to
-		else if ( $t_box_title == 'assigned' && ( current_user_is_anonymous() OR user_get_assigned_open_bug_count( $t_current_user_id, $t_project_id ) == 0 ) ) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+		# If the filter is for a specific project, only use that project
+		if (array_key_exists('project_id', $filter) && $filter['project_id'] != 0)
+			$t_filter_project_id = $filter['project_id'];
+		else
+			$t_filter_project_id = $t_project_id;
 
-		# don't display "Monitored by Me" bugs to users that can't monitor bugs
-		else if ( $t_box_title == 'monitored' && ( current_user_is_anonymous() OR !access_has_project_level( config_get( 'monitor_bug_threshold' ), $t_project_id, $t_current_user_id ) ) ) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+		if ( ON == $t_boxes_position ) {
+			# for even box number start new row and column
+			if ( 1 == $t_counter %2 ) {
+				echo '<tr><td valign="top" width="50%">';
 
-		# don't display "Reported by Me" bugs to users that can't report bugs
-		else if ( in_array( $t_box_title, array( 'reported', 'feedback', 'verify' ) ) && 
-				( current_user_is_anonymous() OR !access_has_project_level( config_get( 'report_bug_threshold' ), $t_project_id, $t_current_user_id ) ) ) {
-			$t_number_of_boxes = $t_number_of_boxes - 1;
-		}
+				print_filter_my_view_box(
+						$filter['name'],
+						$f_page_number,
+						$t_per_page,
+						$filter['filter'],
+						$t_filter_project_id,
+						$t_current_user_id,
+						null,
+						array_key_exists('url', $filter)?"view_all_set.php?type=1&amp;temporary=y&amp;". $filter['url']:null
+					);
+				echo '</td>';
+			}
 
-		# display the box
-		else {
-			$t_counter++;
+			# for odd box number only start new column
+			elseif ( 0 == $t_counter %2 ) {
+				echo '<td valign="top" width="50%">';
 
-			# check the style of displaying boxes - fixed (ie. each box in a separate table cell) or not
-			if ( ON == $t_boxes_position ) {
-				# for even box number start new row and column
-				if ( 1 == $t_counter%2 ) {
-					echo '<tr><td valign="top" width="50%">';
-					include( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'my_view_inc.php' );
-					echo '</td>';
-				}
+				print_filter_my_view_box(
+						$filter['name'],
+						$f_page_number,
+						$t_per_page,
+						$filter['filter'],
+						$t_filter_project_id,
+						$t_current_user_id,
+						null,
+						array_key_exists('url', $filter)?"view_all_set.php?type=1&amp;temporary=y&amp;". $filter['url']:null
+					);
 
-				# for odd box number only start new column
-				elseif ( 0 == $t_counter%2 ) {
-					echo '<td valign="top" width="50%">';
-					include( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'my_view_inc.php' );
-					echo '</td></tr>';
-				}
+				echo '</td></tr>';
+			}
 
-				# for odd number of box display one empty table cell in second column
-				if ( ( $t_counter == $t_number_of_boxes ) && 1 == $t_counter%2 ) {
-					echo '<td valign="top" width="50%"></td></tr>';
-				}
+			# for odd number of box display one empty table cell in second column
+			if ( ( $t_counter == $t_number_of_boxes ) && 1 == $t_counter ) {
+				echo '<td valign="top" width="50%"></td></tr>';
 			}
-			else if ( OFF == $t_boxes_position ) {
-				# start new table row and column for first box
-				if ( 1 == $t_counter ) {
-					echo '<tr><td valign="top" width="50%">';
-				}
 
-				# start new table column for the second half of boxes
-				if ( $t_counter == ceil ($t_number_of_boxes/2) + 1 ) {
-					echo '<td valign="top" width="50%">';
-				}
+		}
+	else {
+			# start new table row and column for first box
+			if ( 1 == $t_counter ) {
+				echo '<tr><td valign="top" width="50%">';
+			}
 
-				# display the required box
-				include( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'my_view_inc.php' );
-				echo '<br />';
+			# start new table column for the second half of boxes
+			if ( $t_counter == ceil ($t_number_of_boxes/2) + 1 ) {
+				echo '<td valign="top" width="50%">';
+			}
 
-				# close the first column for first half of boxes
-				if ( $t_counter == ceil ($t_number_of_boxes/2) ) {
-					echo '</td>';
-				}
+			# display the required box
 
-				# close the table row after all of the boxes
-				if ( $t_counter == $t_number_of_boxes ) {
-					echo '</td></tr>';
-				}
+			print_filter_my_view_box(
+					$filter['name'],
+					$f_page_number,
+					$t_per_page,
+					$filter['filter'],
+					$t_filter_project_id,
+					$t_current_user_id,
+					null,
+					array_key_exists('url', $filter)?"view_all_set.php?type=1&amp;temporary=y&amp;". $filter['url']:null
+				);
+
+			echo '<br />';
+
+			# close the first column for first half of boxes
+			if ( $t_counter == ceil ($t_number_of_boxes/2) ) {
+				echo '</td>';
 			}
+
+			# close the table row after all of the boxes
+			if ( $t_counter == $t_number_of_boxes ) {
+				echo '</td></tr>';
+			}
 		}
 	}
 
-?>
-
-<?php
 	if ( $t_status_legend_position == STATUS_LEGEND_POSITION_BOTTOM || $t_status_legend_position == STATUS_LEGEND_POSITION_BOTH ) {
 		echo '<tr>';
 		echo '<td colspan="2">';
mkornatzki

mkornatzki

2008-05-31 16:19

reporter   ~0017973

i really like this feature. i made a patch (configurable_my_view.patch) against the actual trunk.

You have to download the archive customMyView_v2.tar.gz and follow the readme. instead of using the diff-file of the archive use the new patch.

AMonsef

AMonsef

2008-08-27 02:26

reporter   ~0019252

hi all,

i am running Mantis in our company 6 months ago over iSeries using Mysql, i am trying now to apply this patch but i had this error:

Hmm... I can't seem to find a patch in there anywhere.

could you please advice?

thanks

mnoznica

mnoznica

2009-01-13 07:23

reporter   ~0020602

I have fixed the problem about filters of another user replacing the line:
else if (!is_null($p_user_id) && $p_user_id != $filter['user_id'])
to
else if (!is_null($p_user_id) && $p_user_id != $filter['user_id'] && $filter['is_public'] == 0 )

in the filter_exists function off filter_api.php

This allow the public filters be added by all users

cmfitch1

cmfitch1

2009-10-13 15:31

reporter   ~0023168

This seems like an important thing to do in order to really make the my view page useful. Was there a problem with the submitted change that the development team didn't like? I applied it to 1.2.0 and with a little bit of playing around had it working. I need to do a full code review and more testing, and I'm not sure if something needs to be done to automate the addition of a database table, but I'll attach a git patch shortly if that's all this is waiting on.

squarebox

squarebox

2010-08-26 22:57

reporter   ~0026481

@cmfitch1: do you by chance have a patch that works with 1.2.2 or were you ever abel to get around to making one for 1.2.0?

As an addition to this feature, it'd be great if one could also change the display order of the view boxes view user preference would be great as well.

daryn

daryn

2010-09-28 20:50

reporter   ~0026898

See http://github.com/daryn/mantisbt/tree/save-filter for a similar feature branch against current trunk. This feature is nearly ready to commit and could use some additional testers.

Bozz

Bozz

2011-03-18 04:48

reporter   ~0028438

Last edited: 2011-03-18 04:49

View 2 revisions

Souldn't it be integrated as a plugin instead of a patch ?

dregad

dregad

2011-09-26 15:27

developer   ~0029867

daryn, I had a quick look at your branch, but unfortunately it does not apply cleanly on the latest trunk... Some conflicts are trivial, but others I'm not sure what to do. Any chance you can merge it ?

both modified: css/default.css
both modified: javascript/bugFilter.js
deleted by them: javascript/dev/bugFilter.js
deleted by them: javascript/dev/common.js
both modified: my_view_inc.php
both modified: my_view_page.php

dregad

dregad

2012-10-17 06:35

developer   ~0033250

A possible custom workaround for allowing access level based customization of the my view page was described in 0006480:0033235

atrol

atrol

2013-08-16 12:40

developer   ~0037881

Removed assignment. giallu will not contribute to this issue in near future.

Issue History

Date Modified Username Field Change
2007-03-19 08:02 stefanvandenoord New Issue
2007-07-27 02:29 giallu Relationship added related to 0007065
2007-07-29 22:14 vboctor Note Added: 0015284
2007-07-29 22:14 vboctor Status new => acknowledged
2007-08-04 19:07 giallu Relationship added has duplicate 0007025
2007-10-23 13:55 Nycto File Added: customMyView.diff
2007-10-23 13:56 Nycto Note Added: 0015958
2007-10-23 13:57 Nycto File Added: customMyView.tar.gz
2007-10-23 14:43 jreese Note Added: 0015959
2007-10-23 15:41 Nycto File Added: customMyView_v2.tar.gz
2007-10-23 15:41 Nycto File Added: customMyView_v2.diff
2007-10-23 15:42 Nycto Note Added: 0015960
2007-10-24 05:10 giallu Note Added: 0015969
2007-10-24 12:41 vboctor Status acknowledged => assigned
2007-10-24 12:41 vboctor Assigned To => giallu
2007-12-29 06:15 vboctor Status assigned => acknowledged
2008-03-05 06:20 ghohm Note Added: 0017258
2008-03-05 08:19 mauro File Added: mantis1.GIF
2008-03-05 08:22 mauro Note Added: 0017260
2008-03-05 08:23 mauro Note Edited: 0017260
2008-03-05 11:22 ghohm Note Added: 0017261
2008-03-07 17:30 mkornatzki Note Added: 0017286
2008-03-10 05:18 mauro Note Added: 0017304
2008-05-31 16:13 mkornatzki File Added: configurable_my_view.patch
2008-05-31 16:19 mkornatzki Note Added: 0017973
2008-08-27 02:26 AMonsef Note Added: 0019252
2009-01-13 07:23 mnoznica Note Added: 0020602
2009-10-13 15:31 cmfitch1 Note Added: 0023168
2010-03-17 17:43 ihristov Tag Attached: 765765
2010-08-26 22:57 squarebox Note Added: 0026481
2010-09-28 20:50 daryn Note Added: 0026898
2011-03-18 04:48 Bozz Note Added: 0028438
2011-03-18 04:49 Bozz Note Edited: 0028438 View Revisions
2011-09-26 11:11 atrol Relationship added has duplicate 0013348
2011-09-26 15:27 dregad Note Added: 0029867
2011-09-30 05:13 atrol Relationship added has duplicate 0013358
2011-10-18 20:15 dregad Relationship added has duplicate 0005048
2011-10-18 20:17 dregad Relationship added has duplicate 0005832
2011-10-18 20:18 dregad Relationship added has duplicate 0006412
2011-10-18 20:19 dregad Relationship replaced has duplicate 0007065
2012-03-05 14:07 atrol Relationship added has duplicate 0014007
2012-10-05 15:10 atrol Tag Detached: 765765
2012-10-17 06:35 dregad Relationship added has duplicate 0006480
2012-10-17 06:35 dregad Note Added: 0033250
2013-04-11 17:50 atrol Relationship added has duplicate 0015741
2013-08-16 12:40 atrol Note Added: 0037881
2013-08-16 12:40 atrol Assigned To giallu =>
2016-11-10 04:08 atrol Relationship added related to 0021895