Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1293 dpurdie 1
###############################################################################
2
# Codestriker: Copyright (c) 2001, 2002 David Sitsky.  All rights reserved.
3
# sits@users.sourceforge.net
4
#
5
# This program is free software; you can redistribute it and modify it under
6
# the terms of the GPL.
7
 
8
# Action object for displaying a list of topics.
9
 
10
package Codestriker::Action::ListTopics;
11
 
12
use strict;
13
use Codestriker::Http::Template;
14
use Codestriker::Model::Topic;
15
 
16
# If the input is valid, list the appropriate topics.
17
sub process($$$) {
18
    my ($type, $http_input, $http_response) = @_;
19
 
20
    my $query = $http_response->get_query();
21
 
22
    # Check if this action is allowed.
23
    if ($Codestriker::allow_searchlist == 0) {
24
	$http_response->error("This function has been disabled");
25
    }
26
 
27
    # Obtain a new URL builder object.
28
    my $url_builder = Codestriker::Http::UrlBuilder->new($query);
29
 
30
    my $mode = $http_input->get('mode');
31
    my $feedback = $http_input->get('feedback');
32
    my $projectid = $http_input->get('projectid');
33
 
34
    my ( $sauthor, $sreviewer, $scc, $sbugid,
35
         $sstate, $sproject, $stext,
36
         $stitle, $sdescription,
37
	 $scomments, $sbody, $sfilename,
38
         $sort_order) = get_topic_list_query_params($http_input);
39
 
40
    # Query the model for the specified data.
41
    my @topics = Codestriker::Model::Topic->query($sauthor, $sreviewer, $scc, $sbugid,
42
				     $sstate, $sproject, $stext,
43
				     $stitle, $sdescription,
44
				     $scomments, $sbody, $sfilename,
45
                                     $sort_order);
46
 
47
    # Display the data, with each topic title linked to the view topic screen.
48
    # If only a single project id is being searched over, set that id in the
49
    # cookie.
50
    my @project_ids = ();
51
    if ($sproject ne "") {
52
	@project_ids = split ',', $sproject;
53
    }
54
    my $projectid_cookie = ($#project_ids == 0) ? $project_ids[0] : "";
55
 
56
    $http_response->generate_header(topic_title=>"Topic List", 
57
				    projectid=>$projectid_cookie, 
58
				    topicsort=>join(',',@$sort_order),
59
				    reload=>0, cache=>0);
60
 
61
    # Create the hash for the template variables.
62
    my $vars = {};
63
    $vars->{'feedback'} = $feedback;
64
 
65
    # Store the search parameters, which become hidden fields.
66
    $vars->{'sauthor'} = $sauthor;
67
    $vars->{'sreviewer'} = $sreviewer;
68
    $vars->{'scc'} = $scc;
69
    $vars->{'sbugid'} = $sbugid;
70
    $vars->{'stext'} = $stext;
71
    $vars->{'sstate'} = $sstate;
72
    $vars->{'stitle'} = $stitle;
73
    $vars->{'sdescription'} = $sdescription;
74
    $vars->{'scomments'} = $scomments;
75
    $vars->{'sbody'} = $sbody;
76
    $vars->{'sfilename'} = $sfilename;
77
 
78
    # Collect the comment metric counts that they want to show on the main page.
79
    my @comment_metric_names;
80
    foreach my $comment_state_metric (@{$Codestriker::comment_state_metrics}) {
81
        if (exists($comment_state_metric->{show_on_mainpage})) {
82
            foreach my $value (@{$comment_state_metric->{show_on_mainpage}}) {
83
                push @comment_metric_names,
84
		     { name => $comment_state_metric->{name},
85
		       value => $value };
86
            }
87
        }
88
    }
89
 
90
    $vars->{'commentmetrics'} = \@comment_metric_names;
91
 
92
    # The url generated here includes all of the search parameters, so
93
    # that the current list of topics the user it viewing does not
94
    # revert back to the default open topic list.  The search is
95
    # applied each time they change the sort order.
96
    $vars->{'list_sort_url'} = 
97
	$url_builder->list_topics_url($sauthor, $sreviewer, $scc, $sbugid,
98
				      $stext, $stitle,
99
				      $sdescription, $scomments,
100
				      $sbody, $sfilename,
101
				      [ split ',', $sstate] , \@project_ids);
102
 
103
    $vars->{'list_sort_url_rss'} = 
104
	$url_builder->list_topics_url_rss($sauthor, $sreviewer, $scc, $sbugid,
105
				      $stext, $stitle,
106
				      $sdescription, $scomments,
107
				      $sbody, $sfilename,
108
				      [ split ',', $sstate] , \@project_ids);
109
 
110
    # The list of topics in the template toolkit.
111
    my @template_topics;
112
 
113
    # For each topic, collect all the reviewers, CC, and bugs, and display it
114
    # as a row in the table.  Each bug should be linked appropriately. 
115
    foreach my $topic (@topics) {
116
 
117
        # do the easy stuff first, 1 to 1 mapping into the template.
118
 
119
	my $template_topic = {};
120
 
121
	$template_topic->{'view_topic_url'} = 
122
	    $url_builder->view_url($topic->{topicid}, -1, $mode,
123
				   $Codestriker::default_topic_br_mode);
124
 
125
	$template_topic->{'description'} = $topic->{description};
126
 
127
	$template_topic->{'created'} =
128
	    Codestriker->format_short_timestamp($topic->{creation_ts});
129
 
130
	$template_topic->{'id'}      = $topic->{topicid};
131
	$template_topic->{'title'}   = $topic->{title};
132
 
133
	$template_topic->{'version'} = $topic->{version};
134
 
135
	$template_topic->{'state'}   = $Codestriker::topic_states[$topic->{topic_state_id}];
136
 
137
	# Only include the username part of the email address to save space.
138
	my $accum_author = $topic->{author};
139
        $accum_author =~ s/\@.*$//o;
140
	$template_topic->{'author'} = $accum_author;
141
 
142
        # cc
143
	my $cc = $topic->{cc};
144
        $cc =~ s/\@.*$//o;
145
	$template_topic->{'cc'}     = $cc;
146
 
147
        # bug ids
148
	my @accum_bugs = split /, /, $topic->{bug_ids};
149
	for ( my $index = 0; $index < scalar(@accum_bugs); ++$index) {
150
	    $accum_bugs[$index] =
151
		$query->a({href=>"$Codestriker::bugtracker$accum_bugs[$index]"},
152
                    $accum_bugs[$index]);
153
	}
154
	$template_topic->{'bugids'} = join ', ', @accum_bugs;
155
 
156
        # do the reviewers
157
        my @reviewers_vistited = 
158
            $topic->get_metrics()->get_list_of_actual_topic_participants();
159
 
160
	my @reviewers = split /, /, $topic->{reviewers};
161
	for ( my $index = 0; $index < scalar(@reviewers); ++$index) {
162
 
163
            my $reviewer = $reviewers[$index];
164
 
165
            my $is_visted = 0;
166
            foreach my $visted (@reviewers_vistited) {
167
                if ($visted eq $reviewer) {
168
                    $is_visted = 1;
169
                    last;
170
                }
171
	    }
172
 
173
	    # Output the accumulated information into the row.  Only
174
	    # include the username part of an email address for now to
175
	    # save some space.  This should be made a dynamic option
176
	    # in the future.
177
            $reviewer =~ s/\@.*$//o;
178
 
179
            if ( $is_visted == 0) {
180
                $reviewer = "(" . $reviewer . ")";
181
            }           
182
 
183
            $reviewers[$index] = $reviewer;      
184
                    }
185
 
186
	$template_topic->{'reviewer'} = join(", ",@reviewers);
187
 
188
        my @main_page_comment_metrics = ();
189
        foreach my $comment_state_metric (@{$Codestriker::comment_state_metrics}) {
190
 
191
            if ( exists($comment_state_metric->{show_on_mainpage})) {
192
                foreach my $value (@{$comment_state_metric->{show_on_mainpage}}) {
193
 
194
                    my $count = $topic->get_comment_metric_count($comment_state_metric->{name},$value);
195
 
196
                    my $template_comment_metric = 
197
                    {
198
                        name  => $comment_state_metric->{name},
199
                        value => $value,
200
                        count => $count
201
                    };
202
 
203
                    push @main_page_comment_metrics,$template_comment_metric;
204
		}
205
	    }
206
	}
207
 
208
        $template_topic->{'commentmetrics'} = \@main_page_comment_metrics;
209
 
210
	push @template_topics, $template_topic;
211
    }
212
 
213
    $vars->{'topics'} = \@template_topics;
214
    $vars->{'states'} = \@Codestriker::topic_states;
215
 
216
    $vars->{'list_projects_url'} = $url_builder->list_projects_url();
217
    $vars->{'view_metrics_url'} = $url_builder->metric_report_url();
218
 
219
    my $template = Codestriker::Http::Template->new("listtopics");
220
    $template->process($vars);
221
 
222
    $http_response->generate_footer();
223
}
224
 
225
# Process the input and return the parts that will feed into the topic
226
# list query. Returns in the same order that the topic query function
227
# takes them.
228
sub get_topic_list_query_params {
229
    my ($http_input) = @_;
230
 
231
    # Check that the appropriate fields have been filled in.
232
    my $sauthor = $http_input->get('sauthor') || "";
233
    my $sreviewer = $http_input->get('sreviewer') || "";
234
    my $scc = $http_input->get('scc') || "";
235
    my $sbugid = $http_input->get('sbugid') || "";
236
    my $stext = $http_input->get('stext') || "";
237
    my $sstate = $http_input->get('sstate');
238
    my $sproject = $http_input->get('sproject');
239
    my $stitle = $http_input->get('stitle') || 0;
240
    my $sdescription = $http_input->get('sdescription') || 0;
241
    my $scomments = $http_input->get('scomments') || 0;
242
    my $sbody = $http_input->get('sbody') || 0;
243
    my $sfilename = $http_input->get('sfilename') || 0;
244
    my $projectid = $http_input->get('projectid');
245
 
246
    # If $sproject has been set to -1, then retrieve the value of the projectid
247
    # from the cookie as the project search value.  This is done to facilate
248
    # integration with other systems, which jump straight to this URL, and
249
    # set the cookie explicitly.
250
    if ($sproject eq "-1") {
251
	$sproject = (defined $projectid) ? $projectid : "";
252
    }
253
 
254
    # Only show open topics if codestriker.pl was run without parameters.
255
    if (defined($http_input->{query}->param) == 0 || !defined($sstate)) {
256
    	$sstate = join(',', @Codestriker::default_states_indexes);
257
    }
258
 
259
    # handle the sort order of the topics.
260
    my @sort_order = get_topic_sort_order($http_input);
261
 
262
    return ( $sauthor, $sreviewer, $scc, $sbugid,
263
				     $sstate, $sproject, $stext,
264
				     $stitle, $sdescription,
265
				     $scomments, $sbody, $sfilename,
266
                                     \@sort_order);
267
}
268
 
269
# Process the topic_sort_change input request (if any), and the current sort 
270
# cookie (topicsort), and returns a list that defines the topic sort order
271
# that should be used for this request. The function will ensure that 
272
# column types are not repeated, and will sort in the opposite direction
273
# if the user clicks on the same column twice.
274
sub get_topic_sort_order {
275
    my ($http_input) = @_;
276
 
277
    my $topic_sort_change = $http_input->get('topic_sort_change');
278
    my $topicsort = $http_input->get('topicsort');
279
 
280
    my @sort_order = split(/,/,$topicsort); # this is always from the cookie.
281
 
282
    if ($topic_sort_change ne "") {
283
        if (scalar(@sort_order) > 0) {
284
 
285
            # If the user clicked on the same column twice in a row, reverse
286
            # the direction of the sort.
287
 
288
            $sort_order[0] =~ s/\+$topic_sort_change/\-$topic_sort_change/ or
289
            $sort_order[0] =~ s/\-$topic_sort_change/\+$topic_sort_change/ or        
290
            unshift @sort_order, "+" . $topic_sort_change;
291
        }
292
        else {
293
            unshift @sort_order, "+" . $topic_sort_change;
294
        }
295
 
296
        # look for duplicate sort keys, and remove
297
        my %sort_hash;
298
 
299
        for ( my $index = 0; 
300
              $index < scalar( @sort_order); 
301
              # Incremented in the if...
302
              ) {
303
 
304
            # chew off the leading +-
305
            my $current = $sort_order[$index];
306
 
307
            if ($current =~ s/^[\+\-]//) {
308
                if (exists $sort_hash{$current}) {
309
                    # remove from the list.
310
                    splice @sort_order, $index,1;
311
                }
312
                else {
313
                    # have not seem this before, keep it, and look at the next
314
                    # string.
315
                    ++$index;                
316
                }
317
 
318
                $sort_hash{$current} = 1;
319
            } 
320
        }
321
    }
322
 
323
    # Pull out any elements that are not valid (from a bad cookie or from a bad
324
    # input.
325
 
326
    for (my $index = 0; $index < scalar(@sort_order) ; ++$index) {
327
 
328
        if ($sort_order[$index] ne "+title" && $sort_order[$index] ne "-title" &&
329
            $sort_order[$index] ne "+author" && $sort_order[$index] ne "-author" &&
330
            $sort_order[$index] ne "+created" && $sort_order[$index] ne "-created" &&
331
            $sort_order[$index] ne "+state" && $sort_order[$index] ne "-state") {
332
 
333
            splice @sort_order,$index,1;
334
            --$index;
335
        }
336
    }
337
 
338
    return @sort_order;
339
}
340
 
341
1;