flurin-ticgit 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
data/bin/ti ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This is a command line client that does all the actual tic commands
4
+ #
5
+ # authors: Scott Chacon <schacon@gmail.com>
6
+ # Mislav Marohnić <mislav.marohnic@gmail.com>
7
+
8
+ require File.dirname(__FILE__) + "/../lib/ticgit"
9
+
10
+ TicGit::CLI::start()
data/bin/ticgitweb ADDED
@@ -0,0 +1,517 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # starts a sinatra based web server that provides an interface to
4
+ # your ticgit tickets
5
+ #
6
+ # some of the sinatra code borrowed from sr's git-wiki
7
+ #
8
+ # author: Flurin Egger
9
+ # original author : Scott Chacon (schacon@gmail.com)
10
+ #
11
+
12
+ def require_dependency_with_check(dependency)
13
+ begin
14
+ require dependency
15
+ rescue LoadError => e
16
+ puts "You need to install #{dependency} before we can proceed"
17
+ end
18
+ end
19
+
20
+ require_dependency_with_check 'rubygems'
21
+
22
+ # We need a sinatra version bigger than 0.3.1
23
+ gem 'sinatra', "~> 0.3.1"
24
+
25
+ %w(sinatra git ticgit haml sass).each do |dependency|
26
+ require_dependency_with_check dependency
27
+ end
28
+
29
+
30
+ configure do
31
+ enable :sessions
32
+ end
33
+ use_in_file_templates!
34
+
35
+ # !! TODO : if ARGV[1] is a path to a git repo, use that
36
+ # otherwise, look in ~/.ticgit
37
+
38
+ $ticgit = TicGit.open('.')
39
+
40
+ # Always load saved searches. (used in navigation)
41
+ before do
42
+ @saved = $ticgit.config['list_options'].keys rescue []
43
+ end
44
+
45
+ # Stylesheets
46
+ get('/_stylesheet.css') do
47
+ header("Content-Type" => "text/css;charset=utf-8")
48
+ sass :stylesheet_all
49
+ end
50
+ get('/_print.css') do
51
+ header("Content-Type" => "text/css;charset=utf-8")
52
+ sass :stylesheet_print
53
+ end
54
+
55
+ # ticket list view
56
+ get '/' do
57
+ @tickets = $ticgit.ticket_list(:order => 'date.desc')
58
+ store_list_url!
59
+ haml :list, :locals => {:title => "All tickets"}
60
+ end
61
+
62
+ get '/fs/:state' do
63
+ @tickets = $ticgit.ticket_list(:state => params[:state], :order => 'date.desc')
64
+ store_list_url!
65
+ haml :list, :locals => {:title => "#{params[:state].to_s.capitalize} tickets"}
66
+ end
67
+
68
+ get '/tag/:tag' do
69
+ @tickets = $ticgit.ticket_list(:tag => params[:tag], :order => 'date.desc')
70
+ store_list_url!
71
+ haml :list, :locals => {:title => "All tickets with tag '#{params[:tag]}'"}
72
+ end
73
+
74
+ get '/sv/:saved_view' do
75
+ @tickets = $ticgit.ticket_list(:saved => params[:saved_view])
76
+ store_list_url!
77
+ haml :list, :locals => {:title => "All tickets in view '#{params[:saved_view]}'"}
78
+ end
79
+
80
+
81
+ # new ticket
82
+ get '/tickets/new' do
83
+ haml :new, :locals => {:title => "Create new ticket"}
84
+ end
85
+
86
+ # create ticket
87
+ post '/tickets' do
88
+ title = params[:title].to_s.strip
89
+ if title.size > 1
90
+ tags = params[:tags].split(',').map { |t| t.strip } rescue nil
91
+ t = $ticgit.ticket_new(title, {:description => params[:description].strip, :tags => tags})
92
+ if params[:addmore]
93
+ redirect '/tickets/new?addmore=true'
94
+ else
95
+ redirect session[:recent_list_url] || "/"
96
+ end
97
+ else
98
+ redirect '/tickets/new'
99
+ end
100
+ end
101
+
102
+ # show ticket
103
+ get '/tickets/:ticket' do
104
+ @ticket = $ticgit.ticket_show(params[:ticket])
105
+ haml :show, :locals => {:title => "Ticket #{@ticket.ticket_id}"}
106
+ end
107
+
108
+ # update ticket
109
+ put '/tickets/:ticket' do
110
+ @ticket = $ticgit.ticket_show(params[:ticket])
111
+ orig_state = nil
112
+ new_state = nil
113
+ new_tags = nil
114
+ if params[:state] && $ticgit.tic_states.include?(params[:state]) && @ticket.state != params[:state]
115
+ orig_state = @ticket.state
116
+ new_state = params[:state]
117
+ @ticket.change_state(params[:state])
118
+ end
119
+ if params[:tags]
120
+ current_tags = @ticket.tags
121
+ posted_tags = params[:tags].split(",").map{|s| s.strip }
122
+ tags_to_remove = current_tags - posted_tags
123
+ tags_to_add = posted_tags - current_tags
124
+ tags_to_remove.each{|t| @ticket.remove_tag(t) }
125
+ tags_to_add.each{|t| @ticket.add_tag(t) }
126
+ new_tags = posted_tags if tags_to_remove.any? || tags_to_add.any?
127
+ end
128
+
129
+ if params[:comment] && params[:comment].strip != ""
130
+ comment = ""
131
+ comment = "Set state from #{orig_state} to #{new_state}\n\n" if new_state
132
+ @ticket.add_comment(comment + params[:comment])
133
+ end
134
+
135
+ $ticgit.reset_ticgit
136
+
137
+ if ["resolved","invalid"].include?(params[:state]) && session[:recent_list_url]
138
+ # If the ticket is resolved or invalid return to the last listview
139
+ redirect session[:recent_list_url]
140
+ else
141
+ redirect "/tickets/#{@ticket.ticket_id}"
142
+ end
143
+ end
144
+
145
+
146
+ ## Helper methods
147
+
148
+ #
149
+ def store_list_url!
150
+ session[:recent_list_url] = request.fullpath
151
+ end
152
+
153
+
154
+ __END__
155
+ @@ layout
156
+ :plain
157
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
158
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
159
+ %html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang=>"en"}
160
+ %head
161
+ %title= title
162
+ %link{:rel => 'stylesheet', :href => '/_stylesheet.css', :type => 'text/css', :media => 'all'}
163
+ %link{:rel => 'stylesheet', :href => '/_print.css', :type => 'text/css', :media => 'print'}
164
+ %meta{'http-equiv' => 'Content-Type', :content => 'text/html; charset=utf-8'}
165
+ %body
166
+ #wrapper
167
+ #action
168
+ %a{:href => '/tickets/new'} New Ticket
169
+ %ul#navigation
170
+ %li
171
+ %a{:href => '/'} All
172
+ %li
173
+ %a{:href => '/fs/open'} Open
174
+ %li
175
+ %a{:href => '/fs/resolved'} Resolved
176
+ %li
177
+ %a{:href => '/fs/hold'} Hold
178
+ %li
179
+ %a{:href => '/fs/invalid'} Invalid
180
+ - if @saved && !@saved.empty?
181
+ %li | Saved:
182
+ %ul.saved
183
+ - @saved.each do |s|
184
+ %li
185
+ %a{:href => "/sv/\#{s}"}= s
186
+
187
+ = yield
188
+
189
+ @@ list
190
+ %h1= title
191
+ - if @tickets.empty?
192
+ %p No tickets found.
193
+ - else
194
+ %table.long
195
+ %thead
196
+ %tr
197
+ %th SHA
198
+ %th.ticket Ticket
199
+ %th State
200
+ %th Created&nbsp;at
201
+ %th Created&nbsp;by
202
+ %th Tags
203
+ %tbody
204
+ - c = 'even'
205
+ - @tickets.each do |t|
206
+ %tr{:class => (c == 'even' ? c = 'odd' : c = 'even') }
207
+ %td
208
+ %a{:href => "/tickets/#{t.ticket_id}" }
209
+ %code= t.ticket_id[0,6]
210
+ %td
211
+ %strong
212
+ %a{:href => "/tickets/#{t.ticket_id}" }= t.title
213
+ .content~ t.description
214
+ %td
215
+ %span{:class => "state " + t.state, :style => "float: left;"}= t.state
216
+ %td= t.opened.strftime("%m/%d")
217
+ %td= t.assigned_name
218
+ %td
219
+ - t.tags.each do |tag|
220
+ %a.tag{:href => "/tag/#{tag}"}= tag
221
+
222
+ @@ show
223
+ %h1
224
+ = @ticket.title
225
+ .meta
226
+ %span{:class => "state " + @ticket.state}= @ticket.state
227
+ Ticket:
228
+ = @ticket.ticket_id
229
+ %br
230
+ opened at
231
+ %em= @ticket.opened.strftime("%Y-%m-%d")
232
+ assigned to
233
+ %em= @ticket.assigned
234
+ tagged with
235
+ - @ticket.tags.each do |t|
236
+ %a.tag{:href => "/tag/#{t}"}= t
237
+
238
+ .content~ @ticket.description
239
+ %hr/
240
+ %form{:action => "/tickets/#{@ticket.ticket_id}", :method => 'post'}
241
+ %input{:type => "hidden", :name => "_method", :value => "put"}
242
+ %table.twocol
243
+ %tr
244
+ %th State
245
+ %td
246
+ %select{:name => "state", :id => "ticket_state"}
247
+ - $ticgit.tic_states.each do |ts|
248
+ %option{:value => ts , :selected => (@ticket.state == ts ? "selected" : nil)}= ts
249
+ %tr
250
+ %th
251
+ Tags
252
+ %small (comma delimited)
253
+ %td
254
+ %textarea{:rows => 2, :name => "tags", :style => "width: 50%"}= @ticket.tags.join(", ")
255
+ %tr
256
+ %th
257
+ Comment
258
+ %small (optional)
259
+ %td
260
+ %textarea{:rows => 3, :name => "comment", :style => "width: 100%"}
261
+ %tr
262
+ %th
263
+ %td
264
+ %div.submit
265
+ %input{:type => 'submit', :value => 'Update ticket'}
266
+
267
+ %h3 Comments
268
+
269
+ %div.comments
270
+ - @ticket.comments.reverse.each do |t|
271
+ %div.comment
272
+ %span.head
273
+ Added
274
+ = t.added.strftime("%m/%d %H:%M")
275
+ by
276
+ = t.user
277
+ %div.comment-text
278
+ = t.comment.gsub("\n","<br/>")
279
+
280
+ @@ new
281
+ %h1 Create a New Ticket
282
+ %form{:action => '/tickets/new', :method => 'post'}
283
+ %table
284
+ %tr
285
+ %th Title
286
+ %td
287
+ %input{:type => 'text', :name => 'title', :size => 30, :style => "width: 100%"}
288
+ %tr
289
+ %th Description
290
+ %td
291
+ %textarea{:rows => 15, :cols => 30, :name => 'description', :style => "width: 100%"}
292
+ %tr
293
+ %th
294
+ %span Tags
295
+ %small (comma delimited)
296
+ %td
297
+ %textarea{:name => 'tags', :rows => 2, :style => "width: 50%"}
298
+ %tr
299
+ %th
300
+ %td
301
+ %label{:for => "addmore"}
302
+ %input{:type => "checkbox", :value => "1",:id => "addmore", :name => "addmore", :checked => (params["addmore"] ? "checked" : nil)}
303
+ %span Add another ticket
304
+ %tr
305
+ %td
306
+ %td
307
+ %input{:type => 'submit', :value => 'Create Ticket'}
308
+
309
+ @@ stylesheet_all
310
+ body
311
+ :font
312
+ family: Verdana, Arial, "Bitstream Vera Sans", Helvetica, sans-serif
313
+ color: black
314
+ size: 62.5%
315
+ line-height: 1.2
316
+ background-color: white
317
+ margin: 2em
318
+
319
+ #wrapper
320
+ font-size: 1.2em
321
+ width: 90%
322
+ margin: 0 auto
323
+
324
+ // Autoclearing
325
+ #navigation:after
326
+ content: "."
327
+ visibility: hidden
328
+ clear: both
329
+ display: block
330
+ height: 0px
331
+
332
+ // IE autoclearing
333
+ #navigation
334
+ zoom: 1
335
+
336
+ #navigation
337
+ li
338
+ float: left
339
+ margin-right: 0.5em
340
+ a
341
+ background-color: #e0e0e0
342
+ color: black
343
+ text-decoration: none
344
+ padding: 2px
345
+ margin: 0
346
+ list-style: none
347
+ padding: 5px
348
+ border-bottom: 1px black solid
349
+
350
+ #action
351
+ text-align: right
352
+ float: right
353
+ a
354
+ background: #005
355
+ padding: 5px 10px
356
+ font-weight: bold
357
+ color: #fff
358
+ float: left
359
+
360
+ .addtag
361
+ padding: 5px 0
362
+ clear: both
363
+
364
+ h1
365
+ display: block
366
+ padding-bottom: 5px
367
+ margin-bottom: 0
368
+
369
+ h4
370
+ margin: 0 0 0.5em 0
371
+
372
+ div.meta
373
+ margin-bottom: 1em
374
+ display: block
375
+ font-size: 0.9em
376
+ font-weight: normal
377
+ color: #666
378
+ em
379
+ color: #000
380
+ font-style: normal
381
+ font-weight: bold
382
+ a.tag
383
+ font-size: 1em
384
+ float: none
385
+ background: #eee
386
+ color: #000
387
+ span.state
388
+ float: left
389
+ margin-right: 1em
390
+ color: #000
391
+
392
+ div.content
393
+ padding-top: 1em
394
+ clear: both
395
+
396
+ form
397
+ padding: 10px
398
+ background: #f2f2f2
399
+ table
400
+ width: 100%
401
+ tr
402
+ th
403
+ width: 20%
404
+ th,td
405
+ border-bottom: none
406
+ .submit
407
+ margin: 0.5em 0 0 0
408
+
409
+ a
410
+ color: black
411
+ a.exists
412
+ font-weight: bold
413
+ a.unknown
414
+ font-style: italic
415
+
416
+ a.tag
417
+ padding: 2px 5px
418
+ background: #888
419
+ color: #fff
420
+ font-weight: normal
421
+ font-size: 80%
422
+ float: left
423
+ margin: 1px 2px
424
+ text-decoration: none
425
+
426
+ .comments
427
+ margin: 10px 0px
428
+ .comment
429
+ .head
430
+ font-weight: bold
431
+ display: block
432
+ padding: 4px
433
+ .comment-text
434
+ padding: 4px
435
+ padding-bottom: 10px
436
+ margin-bottom: 10px
437
+ color: #333
438
+ border-bottom: 1px solid #aaa
439
+
440
+ table.long
441
+ width: 100%
442
+ .content
443
+ padding: 0
444
+
445
+
446
+ // States
447
+ span.state
448
+ padding: 3px
449
+
450
+ span.open
451
+ background: #ada
452
+ span.resolved
453
+ background: #abd
454
+ span.hold
455
+ background: #dda
456
+ span.invalid
457
+ background: #aaa
458
+
459
+
460
+ table
461
+ font-size: 100%
462
+ border-collapse: collapse
463
+ th
464
+ small
465
+ font-weight: normal
466
+ td,th
467
+ vertical-align: top
468
+ tr.even
469
+ td
470
+ background: #eee
471
+ tr.odd
472
+ td
473
+ background: #fff
474
+
475
+ table
476
+ tr
477
+ td,th
478
+ padding: 3px 5px
479
+ border-bottom: 1px solid #fff
480
+ th
481
+ text-align: left
482
+ vertical-align: top
483
+ th.ticket
484
+ width: 50%
485
+
486
+ strong a
487
+ text-decoration: none
488
+
489
+ table
490
+ thead
491
+ tr
492
+ td,th
493
+ border-bottom: 1px solid #000
494
+
495
+ .submit
496
+ font-size: large
497
+ font-weight: bold
498
+
499
+ .page_title
500
+ font-size: xx-large
501
+
502
+ .edit_link
503
+ color: black
504
+ font-size: 14px
505
+ font-weight: bold
506
+ background-color: #e0e0e0
507
+ font-variant: small-caps
508
+ text-decoration: none
509
+
510
+ @@ stylesheet_print
511
+ #navigation, #action
512
+ display: none
513
+
514
+ table
515
+ tr.odd, tr.even
516
+ td
517
+ border-bottom: 1px solid #ddd