Compare commits

...

346 Commits
0.3.0 ... 0.5.0

Author SHA1 Message Date
Jean-Philippe Lang
3c9a5f1e23 tagged version 0.5.0
git-svn-id: http://redmine.rubyforge.org/svn/tags/0.5.0@444 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-11 15:46:37 +00:00
Jean-Philippe Lang
6a8ddc954f Doc files updated for 0.5.0 release
git-svn-id: http://redmine.rubyforge.org/svn/trunk@443 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-11 15:33:27 +00:00
Jean-Philippe Lang
8f1c0eb2dd Closed issues no longer displayed on "my page" -> "issues assigned to me".
git-svn-id: http://redmine.rubyforge.org/svn/trunk@442 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-11 15:18:36 +00:00
Jean-Philippe Lang
8c01275ee9 Japanese lang file updated (Satoru Kurashiki)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@441 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-11 15:14:44 +00:00
Jean-Philippe Lang
d6f4208a15 Fixed 10031 revision links and auto linking URLs conflict
git-svn-id: http://redmine.rubyforge.org/svn/trunk@440 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-11 15:10:02 +00:00
Jean-Philippe Lang
2e78bc1bc4 Fixed pagination links on admin project listing
git-svn-id: http://redmine.rubyforge.org/svn/trunk@439 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-10 17:08:59 +00:00
Jean-Philippe Lang
20feb44564 Changesets comments truncated at 500 characters on activity view.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@438 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-09 18:18:23 +00:00
Jean-Philippe Lang
1506d3ddab Form to add an attachment on document view is now togglable.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@437 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-09 17:59:31 +00:00
Jean-Philippe Lang
5cb64fff91 Replaced deprecated content_for_layout in the layout.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@436 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-08 20:43:57 +00:00
Jean-Philippe Lang
1adf56664d Replaced hard coded help link.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@435 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-08 18:16:45 +00:00
Jean-Philippe Lang
183ede84fd Various changes on views. On project summary, members are now grouped by role and subprojects are listed inline.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@434 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-08 17:44:54 +00:00
Jean-Philippe Lang
bd9a44c225 Added permissions report (link available on roles list view).
git-svn-id: http://redmine.rubyforge.org/svn/trunk@433 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-07 20:27:19 +00:00
Jean-Philippe Lang
30734ba8e8 Added toggle_link helper.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@432 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-07 18:56:12 +00:00
Jean-Philippe Lang
cf4651b6bb Added link_to_issue helper.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@431 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-07 18:30:01 +00:00
Jean-Philippe Lang
14314b77ee Added a warning message on tracker list for trackers that don't have any workflow defined.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@430 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-07 17:33:07 +00:00
Jean-Philippe Lang
ef71edd331 Added versions due dates on calendar.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@429 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-07 12:16:09 +00:00
Jean-Philippe Lang
708c3c9ec6 Added versions due dates on gantt chart.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@428 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-07 12:09:01 +00:00
Jean-Philippe Lang
c1a5c5b9f8 Removed repository creation callback
git-svn-id: http://redmine.rubyforge.org/svn/trunk@427 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-07 09:49:36 +00:00
Jean-Philippe Lang
1cc7006555 Modified the change_status view to use the form builder.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@426 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-05 18:02:56 +00:00
Jean-Philippe Lang
3f87f3c47a Feature 9867 Allow file upload in comment and add to issue history
git-svn-id: http://redmine.rubyforge.org/svn/trunk@425 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-05 17:20:04 +00:00
Jean-Philippe Lang
f3a1b4e38c Added the ability to easily rollback to a previous version of a wiki page.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@424 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-05 14:45:44 +00:00
Jean-Philippe Lang
7eb4abae80 Removed RedCloth :hard_break option that broke textile rendering.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@423 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-05 14:34:11 +00:00
Jean-Philippe Lang
0ea1b712be "Author" column replaced by "Assigned to" in issue list.
"Assigned to" column added in the csv export.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@422 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-05 07:33:51 +00:00
Jean-Philippe Lang
9cf96580bf RedCloth attribute :hard_break set to true to keep line breaks
git-svn-id: http://redmine.rubyforge.org/svn/trunk@421 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-04 22:16:17 +00:00
Jean-Philippe Lang
46d67cb349 Fixed a regression (crash when an admin with no role on the project try to create an issue)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@420 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-04 21:52:53 +00:00
Jean-Philippe Lang
f7d5141251 Added svn:eol-style native property for various files
git-svn-id: http://redmine.rubyforge.org/svn/trunk@419 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-04 18:20:45 +00:00
Jean-Philippe Lang
8e11dac375 Added gantt and calendar url in robots file, to avoid recursive indexing by bots.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@418 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-04 18:09:28 +00:00
Jean-Philippe Lang
adee6de140 Added a unit test on User#role_for_project
git-svn-id: http://redmine.rubyforge.org/svn/trunk@417 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-04 17:52:07 +00:00
Jean-Philippe Lang
4ed89dc2d3 Fixed User role_for_project method
git-svn-id: http://redmine.rubyforge.org/svn/trunk@416 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-04 17:46:51 +00:00
Jean-Philippe Lang
8e6d575d4e Modified logged_in_user_membership controller method so that it returns a role
git-svn-id: http://redmine.rubyforge.org/svn/trunk@415 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-04 17:32:23 +00:00
Jean-Philippe Lang
e227b92972 Various code cleaning, mainly on User, Permission and IssueStatus models.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@414 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-04 17:26:05 +00:00
Jean-Philippe Lang
a9a082f05c Patch 9725 Email templates of chinese simplified (Andy Wu)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@413 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-04 16:22:00 +00:00
Jean-Philippe Lang
be54cb9531 Feature #9808 Allow user to "change" issue status to the same status
git-svn-id: http://redmine.rubyforge.org/svn/trunk@412 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-04 16:14:26 +00:00
Jean-Philippe Lang
18a6b8e101 Fixed 9793 Preview fail for first wiki page of a project
git-svn-id: http://redmine.rubyforge.org/svn/trunk@411 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-03 22:24:59 +00:00
Jean-Philippe Lang
52ced19e2e Added subprojects issue count on project "Reports" page
git-svn-id: http://redmine.rubyforge.org/svn/trunk@410 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-03 19:48:49 +00:00
Jean-Philippe Lang
1c0971b12c Fixed pagination on users/list (status filter lost)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@409 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-03 19:22:56 +00:00
Jean-Philippe Lang
2db9bdf7a2 Slight modifications on revisions table
git-svn-id: http://redmine.rubyforge.org/svn/trunk@408 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-03 19:16:09 +00:00
Jean-Philippe Lang
a09b2a23b9 Feature 9784 Set status when raising issue.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@407 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-03 18:34:22 +00:00
Jean-Philippe Lang
6d2ecefca0 Quick fix for:
* 9750 sort field is lost, when displaying next part of issues list
* 9782 show issues in page is wrong

Still some problems, eg. status criteria is lost when paginating or sorting on users/list

git-svn-id: http://redmine.rubyforge.org/svn/trunk@406 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-03 17:46:05 +00:00
Jean-Philippe Lang
568c22016a Colored square added on "my page" issue list
git-svn-id: http://redmine.rubyforge.org/svn/trunk@405 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-02 20:24:02 +00:00
Jean-Philippe Lang
6e1b9326e4 Added parent project name (if it exists) on project list and project overview.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@404 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-02 20:17:02 +00:00
Jean-Philippe Lang
3c8a38212e Applied the same column width in different similar views.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@403 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-02 19:27:05 +00:00
Jean-Philippe Lang
eba4af7a9f added svn-executable property on perl scripts
git-svn-id: http://redmine.rubyforge.org/svn/trunk@402 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-02 19:01:31 +00:00
Jean-Philippe Lang
f8a5725214 Renamed the repository management script and removed hard coded parameters.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@401 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-02 19:00:22 +00:00
Jean-Philippe Lang
791077c240 Added some attributes length validations.
Also added some information about attribute length constraints on forms.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@400 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-02 18:44:35 +00:00
Jean-Philippe Lang
bd8de9a6f8 Added the ability to copy an existing workflow when creating a new tracker.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@399 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-02 17:45:21 +00:00
Jean-Philippe Lang
0a82489ddc Added the ability to include subprojects issues on calendar & gantt (options box)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@398 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-02 17:12:02 +00:00
Jean-Philippe Lang
006b8716ed Migration to add identifier attribute on project.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@397 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-02 06:29:09 +00:00
Jean-Philippe Lang
4ff8386e3d Initial commit for svn repository management and access control:
* Identifier attribute added on Project model. Used as the unix group name for the project
* Web services (disabled by default) and scripts for repository management on a remote svn host

git-svn-id: http://redmine.rubyforge.org/svn/trunk@396 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-04-01 19:43:59 +00:00
Jean-Philippe Lang
cb6c8bee47 Patch #9705 Tracker filtering on Main Calendar (Jeffrey Jones)
Slightly edited.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@395 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-31 17:15:30 +00:00
Jean-Philippe Lang
3a35883250 Added calendar-zh.js for chinese translation (Andy Wu)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@394 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-31 15:53:56 +00:00
Jean-Philippe Lang
2a00565bc4 Added chinese simplified translation (Andy Wu)
Fixed rfpdf chinese.rb

git-svn-id: http://redmine.rubyforge.org/svn/trunk@393 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-31 15:51:44 +00:00
Jean-Philippe Lang
5e0e951867 Japanese lang file updated (Satoru KURASHIKI)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@392 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-30 23:02:35 +00:00
Jean-Philippe Lang
4c75bd404b removed hard coded strings in views
git-svn-id: http://redmine.rubyforge.org/svn/trunk@391 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-29 19:02:48 +00:00
Jean-Philippe Lang
2b70760594 patch #9627 Add Side by Side in Diff view (Cyril Mougel)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@390 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-29 18:14:59 +00:00
Jean-Philippe Lang
d8ce97f766 german lang file updated (Thomas Löber)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@389 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-28 17:52:20 +00:00
Jean-Philippe Lang
cf221c8f75 removed filter_html on RedCloth textile conversions
git-svn-id: http://redmine.rubyforge.org/svn/trunk@388 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-27 17:49:52 +00:00
Jean-Philippe Lang
b938c60396 slight svg rendering modifications
git-svn-id: http://redmine.rubyforge.org/svn/trunk@387 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-26 18:13:42 +00:00
Jean-Philippe Lang
3a28fa01b0 added info about textile availabality on admin/info
git-svn-id: http://redmine.rubyforge.org/svn/trunk@386 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-26 18:03:25 +00:00
Jean-Philippe Lang
8a84884d50 added changes counts on the "commits per author" svn stat graph
git-svn-id: http://redmine.rubyforge.org/svn/trunk@385 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-26 17:14:06 +00:00
Jean-Philippe Lang
b103052ff0 replaced an hard coded label
git-svn-id: http://redmine.rubyforge.org/svn/trunk@384 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-26 16:47:35 +00:00
Jean-Philippe Lang
71b6dd232e fixed #9542 sqlite3 exception in db:migrate on AddChangesetCommitDate
git-svn-id: http://redmine.rubyforge.org/svn/trunk@383 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-26 16:41:54 +00:00
Jean-Philippe Lang
1f7863e323 fixed bug 9537 fetch_changesets broken
git-svn-id: http://redmine.rubyforge.org/svn/trunk@382 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-25 22:33:40 +00:00
Jean-Philippe Lang
e951209d68 added pagination on revisions list
git-svn-id: http://redmine.rubyforge.org/svn/trunk@381 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-25 18:18:29 +00:00
Jean-Philippe Lang
0ef114e006 added simple svn statistics graphs, rendered using SVG::Graph
git-svn-id: http://redmine.rubyforge.org/svn/trunk@380 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-25 17:11:46 +00:00
Jean-Philippe Lang
887f11435b Patch #9530 Progress bars for roadmap versions (Nick Read)
Slightly edited and links to issues list added

git-svn-id: http://redmine.rubyforge.org/svn/trunk@379 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-25 12:59:48 +00:00
Jean-Philippe Lang
d7f1b873c8 show anonymous on activity view when a commit has no author
git-svn-id: http://redmine.rubyforge.org/svn/trunk@378 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-25 12:24:07 +00:00
Jean-Philippe Lang
16f9f50f50 SVN commits are now stored in the database, and added to the activity view and the search engine.
New commits are automatically retrieved and stored when consulting the repository in the app. This behaviour can be disabled by unchecking 'Autofecth commits' in configuration settings.
Commits can be fetched offline by running (recommanded at least for the initial import of past commits): 
ruby script/runner "Repository.fetch_changesets"
It will load commits for all of the repositories.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@377 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-25 12:12:15 +00:00
Jean-Philippe Lang
6f1dcdc08f updated INSTALL doc with rake db:migrate instead of the deprecated rake migrate
git-svn-id: http://redmine.rubyforge.org/svn/trunk@376 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-24 20:09:07 +00:00
Jean-Philippe Lang
3cd50da3b0 text formatting setting cached at controller level
git-svn-id: http://redmine.rubyforge.org/svn/trunk@375 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-24 09:16:33 +00:00
Jean-Philippe Lang
0125ec3b48 removed td padding
git-svn-id: http://redmine.rubyforge.org/svn/trunk@374 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-23 23:50:12 +00:00
Jean-Philippe Lang
7611f52faf added some parenthesis
git-svn-id: http://redmine.rubyforge.org/svn/trunk@373 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-23 19:03:22 +00:00
Jean-Philippe Lang
669b2342ff added some parenthesis in views
git-svn-id: http://redmine.rubyforge.org/svn/trunk@372 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-23 19:00:48 +00:00
Jean-Philippe Lang
1493c2a9b4 added roadmap and activity calls in projects functional tests
git-svn-id: http://redmine.rubyforge.org/svn/trunk@371 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-23 15:58:53 +00:00
Jean-Philippe Lang
724ca74f51 patch #9429 Display Wiki edits in activity log (Nick Read)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@370 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-23 15:58:02 +00:00
Jean-Philippe Lang
76d4ac17a2 added 999 as a maximum for time entry hours
git-svn-id: http://redmine.rubyforge.org/svn/trunk@369 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-23 13:11:47 +00:00
Jean-Philippe Lang
8d54d97007 Simple time tracking functionality added. Time can be logged at issue or project level.
There's no aggregation reports for now, it's just possible to see all time entries for a project or an issue.
A new "activities" enumeration is added.
Permission for a role to log time must be set (new "Time tracking" section in role permissions screen).

git-svn-id: http://redmine.rubyforge.org/svn/trunk@368 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-23 12:22:31 +00:00
Jean-Philippe Lang
7cf2d889d8 native eol property set on lang files
git-svn-id: http://redmine.rubyforge.org/svn/trunk@363 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-23 08:15:22 +00:00
Jean-Philippe Lang
59a2d1c974 closed issues are now striked on roadmap
git-svn-id: http://redmine.rubyforge.org/svn/trunk@362 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-23 08:13:59 +00:00
Jean-Philippe Lang
5108a9c6fe german translation improved (thanks to Daniel Weinand)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@361 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-23 08:13:33 +00:00
Jean-Philippe Lang
6e98df0e28 fixed #9397 Roadmap - Distinguishing open and closed issues
(closed) is added at the end of closed issue subjects

git-svn-id: http://redmine.rubyforge.org/svn/trunk@360 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-21 18:56:47 +00:00
Jean-Philippe Lang
f3f75f557a added some diagnostic information on admin/info
git-svn-id: http://redmine.rubyforge.org/svn/trunk@359 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-20 20:03:27 +00:00
Jean-Philippe Lang
8bf5759d26 fixed #9398 RSS feed on custom reports not displaying subproject changes
git-svn-id: http://redmine.rubyforge.org/svn/trunk@358 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-20 18:55:33 +00:00
Jean-Philippe Lang
cbf797ed95 removed a non matching closing select tag
git-svn-id: http://redmine.rubyforge.org/svn/trunk@357 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-20 18:37:53 +00:00
Jean-Philippe Lang
17c4d733d0 fixed #9403 Include "Fixed version" when creating a new issue
git-svn-id: http://redmine.rubyforge.org/svn/trunk@356 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-20 18:37:21 +00:00
Jean-Philippe Lang
dd52fb7e2e accidentally committed a database name change...
git-svn-id: http://redmine.rubyforge.org/svn/trunk@355 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-20 18:34:07 +00:00
Jean-Philippe Lang
b1f5103c75 fixed #9401 New Wiki, cannot create new page (good one)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@354 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-20 18:14:23 +00:00
Jean-Philippe Lang
f19e8af33b fixed #9404 Issue and revision textile links in issue notes
git-svn-id: http://redmine.rubyforge.org/svn/trunk@353 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-20 18:09:14 +00:00
Jean-Philippe Lang
a559c0cfc2 fixed #9401 New Wiki, cannot create new page.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@352 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-20 17:41:04 +00:00
Jean-Philippe Lang
5132252daa added "return false;" for onclick event on unclickable menu items
git-svn-id: http://redmine.rubyforge.org/svn/trunk@351 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-20 17:38:34 +00:00
Jean-Philippe Lang
dfb81dd89c added back "subproject" filter on issue list
git-svn-id: http://redmine.rubyforge.org/svn/trunk@350 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-19 20:31:02 +00:00
Jean-Philippe Lang
59e3802c74 fixed migration scripts to work with mysql 5 running in strict mode
git-svn-id: http://redmine.rubyforge.org/svn/trunk@349 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-19 18:12:35 +00:00
Jean-Philippe Lang
a1d2acd574 fixed #9374 Edit issue doesn't have blank category
git-svn-id: http://redmine.rubyforge.org/svn/trunk@348 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-19 17:46:02 +00:00
Jean-Philippe Lang
8bb60b6474 added a status filter on users/list
git-svn-id: http://redmine.rubyforge.org/svn/trunk@347 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-18 20:44:33 +00:00
Jean-Philippe Lang
143be7ee02 added a setting option to set the feeds content limit
git-svn-id: http://redmine.rubyforge.org/svn/trunk@346 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-18 18:32:59 +00:00
Jean-Philippe Lang
d967bb4a54 added back the anchor for each page on the wiki full export
git-svn-id: http://redmine.rubyforge.org/svn/trunk@345 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-18 16:52:25 +00:00
Jean-Philippe Lang
fd37f37ee4 fixed problems when svn path doesn't point to the root directory of the repository.
a root_url property has been added on the repository. it's automatically retrieved the first time the repository is browsed

git-svn-id: http://redmine.rubyforge.org/svn/trunk@344 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-18 15:48:05 +00:00
Jean-Philippe Lang
db3e8616c8 better rendering time for projects/calendar
git-svn-id: http://redmine.rubyforge.org/svn/trunk@343 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-18 10:17:59 +00:00
Jean-Philippe Lang
8fdef1f820 admin menu modification
git-svn-id: http://redmine.rubyforge.org/svn/trunk@342 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-18 10:17:21 +00:00
Jean-Philippe Lang
b481e76ee2 members are now sorted according to roles order on projects/show
removed the useless "members" item in the project menu

git-svn-id: http://redmine.rubyforge.org/svn/trunk@341 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-17 17:44:29 +00:00
Jean-Philippe Lang
3477f9bfe0 added feed icon
git-svn-id: http://redmine.rubyforge.org/svn/trunk@340 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-17 15:51:26 +00:00
Jean-Philippe Lang
10cf1ccc1a added rss/atom feeds at project levels for:
* news
* new issues reported
* details of issue changes

issue cutom queries can be used as feeds

git-svn-id: http://redmine.rubyforge.org/svn/trunk@339 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-17 15:18:50 +00:00
Jean-Philippe Lang
22b42dc90a fixed self.down in AddSearchPermission migration
git-svn-id: http://redmine.rubyforge.org/svn/trunk@338 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-17 14:50:08 +00:00
Jean-Philippe Lang
e6f58e4dcc fixed #9308 table_name pre/suffix support
git-svn-id: http://redmine.rubyforge.org/svn/trunk@337 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-15 22:11:02 +00:00
Jean-Philippe Lang
192b9008bd fixed: error on feeds/news when no news exist
git-svn-id: http://redmine.rubyforge.org/svn/trunk@336 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-15 19:20:49 +00:00
Jean-Philippe Lang
56d0af472d removed project_id presence validation on wiki model which was failing when creating a project with a wiki
git-svn-id: http://redmine.rubyforge.org/svn/trunk@335 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-14 17:23:38 +00:00
Jean-Philippe Lang
85f32b956f added italian translation [Alessio Spadaro]
git-svn-id: http://redmine.rubyforge.org/svn/trunk@334 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-12 18:34:25 +00:00
Jean-Philippe Lang
027bf93849 added svn:eol-style native property on /app files
git-svn-id: http://redmine.rubyforge.org/svn/trunk@333 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-12 17:59:02 +00:00
Jean-Philippe Lang
071f8e18d0 fixed #9207 Can't Save Changes to Project
git-svn-id: http://redmine.rubyforge.org/svn/trunk@332 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-12 17:33:20 +00:00
Jean-Philippe Lang
19d962c3aa added svn:executable property on the scripts
git-svn-id: http://redmine.rubyforge.org/svn/trunk@331 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-12 17:29:04 +00:00
Jean-Philippe Lang
dae2d4686e width of all wiki content textareas set to 99.5%
git-svn-id: http://redmine.rubyforge.org/svn/trunk@329 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-11 14:22:53 +00:00
Jean-Philippe Lang
fc3ee67b1f send a 404 when trying to access an unexisting repository
git-svn-id: http://redmine.rubyforge.org/svn/trunk@328 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-11 14:06:05 +00:00
Jean-Philippe Lang
a54a15523b wiki:
* added "Heading" and "Inline quote" buttons to the toolbar
* changed "Link" button behaviour (now produces [[Link]])
* added a simple help on text formatting

git-svn-id: http://redmine.rubyforge.org/svn/trunk@327 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-11 14:00:15 +00:00
Jean-Philippe Lang
5b135c07d0 fixed the "preview" link on wiki/edit
git-svn-id: http://redmine.rubyforge.org/svn/trunk@326 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-10 15:46:34 +00:00
Jean-Philippe Lang
dd83445fd7 extended the search to wiki content
git-svn-id: http://redmine.rubyforge.org/svn/trunk@325 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-10 15:34:38 +00:00
Jean-Philippe Lang
290485b144 added missing calendar-ja.js, partially translated
git-svn-id: http://redmine.rubyforge.org/svn/trunk@324 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-10 15:20:37 +00:00
Jean-Philippe Lang
c514316a2e wiki branch merged into trunk
git-svn-id: http://redmine.rubyforge.org/svn/trunk@323 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-10 15:09:49 +00:00
Jean-Philippe Lang
8b98ceb92c improved search engine
* it's now possible to search for multiple words ("all words" or "one of the words" options)
* added a fixed limit for result count

git-svn-id: http://redmine.rubyforge.org/svn/trunk@321 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-10 13:32:04 +00:00
Jean-Philippe Lang
7a20a4d32b feature #9137 Password-protected SVN repositories
* added login and password attributes on repositories
* fixed svn calls (svn waiting for user input)

git-svn-id: http://redmine.rubyforge.org/svn/trunk@319 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-09 18:03:31 +00:00
Jean-Philippe Lang
8cbb78bb1d patch #9104 Disable cleartext logging of passwords in log files
git-svn-id: http://redmine.rubyforge.org/svn/trunk@310 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-07 17:59:41 +00:00
Jean-Philippe Lang
ef84339003 fixed #9097: Minor rendering problem within Safari at admin/mail_options and roles permissions
git-svn-id: http://redmine.rubyforge.org/svn/trunk@308 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-06 22:46:58 +00:00
Jean-Philippe Lang
909954ac34 fixed dotted hr for IE6
git-svn-id: http://redmine.rubyforge.org/svn/trunk@305 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-06 18:45:08 +00:00
Jean-Philippe Lang
d996643540 adjusted the attachment date column width on pdf issue export to avoid overlapping in japanese
git-svn-id: http://redmine.rubyforge.org/svn/trunk@302 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-05 19:00:16 +00:00
Jean-Philippe Lang
074a4a6e0e fixed #9005: administration-menu doesn't work with prefix-url
git-svn-id: http://redmine.rubyforge.org/svn/trunk@289 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-03 17:35:11 +00:00
Jean-Philippe Lang
a6248cba19 added missing field_is_in_roadmap key in lang files
git-svn-id: http://redmine.rubyforge.org/svn/trunk@288 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-03 10:22:38 +00:00
Jean-Philippe Lang
6a875eb691 fix for #8973: Export feature(to csv/pdf) doesn't work in Japanese
csv and pdf encoding are know defined for each language (general_csv_encoding and general_pdf_encoding keys in lang files)
added SJIS font for japanese pdf exports

git-svn-id: http://redmine.rubyforge.org/svn/trunk@287 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-03-01 19:49:04 +00:00
Jean-Philippe Lang
83c96d4f3e search engine improvements and simple test
git-svn-id: http://redmine.rubyforge.org/svn/trunk@285 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-28 22:35:22 +00:00
Jean-Philippe Lang
1fcc9e977f updated supported language count in test (now 5)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@284 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-28 22:32:45 +00:00
Jean-Philippe Lang
c56b95ed68 patch #8936: Properties changes in a diff are showing as modifications to files
git-svn-id: http://redmine.rubyforge.org/svn/trunk@283 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-28 19:33:07 +00:00
Jean-Philippe Lang
bb3a5bcfd7 patch #8937: Show filename above diff to aid reading multi-file diffs
git-svn-id: http://redmine.rubyforge.org/svn/trunk@282 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-28 19:26:53 +00:00
Jean-Philippe Lang
35678a1c09 brackets removed around "View all changes" on issues/show
git-svn-id: http://redmine.rubyforge.org/svn/trunk@281 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-27 22:07:42 +00:00
Jean-Philippe Lang
c622ad0b50 #8911 Textile formatting for issue notes
git-svn-id: http://redmine.rubyforge.org/svn/trunk@280 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-27 22:07:01 +00:00
Jean-Philippe Lang
75324e4859 added a simple search engine. left to do:
- full content search (only subject/titles for now)
- pagination
- results presentation improvement

git-svn-id: http://redmine.rubyforge.org/svn/trunk@279 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-27 21:03:15 +00:00
Jean-Philippe Lang
93f07c78d6 japanese translation added (thanks to Satoru Kurashiki)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@278 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-27 17:58:59 +00:00
Jean-Philippe Lang
59a619ebbb fixed #8915: crash when adding a user with a wrong length password
git-svn-id: http://redmine.rubyforge.org/svn/trunk@277 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-27 17:26:25 +00:00
Jean-Philippe Lang
77938cc11e fixed: no diff display with one line files [#8883]
git-svn-id: http://redmine.rubyforge.org/svn/trunk@276 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-26 21:32:16 +00:00
Jean-Philippe Lang
ae998984a0 fixed: unable to update repository url
git-svn-id: http://redmine.rubyforge.org/svn/trunk@275 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-26 19:20:18 +00:00
Jean-Philippe Lang
2e31311e3c "#id" patterns are turned into links to issues in descriptions and commit messages
git-svn-id: http://redmine.rubyforge.org/svn/trunk@274 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-25 19:40:57 +00:00
Jean-Philippe Lang
32782a7f9f added back database adapter name on admin/info
git-svn-id: http://redmine.rubyforge.org/svn/trunk@262 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-20 20:17:34 +00:00
Jean-Philippe Lang
4f2d74e25f fixed: error when clicking "add" with no block selected on my/page_layout
git-svn-id: http://redmine.rubyforge.org/svn/trunk@261 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 20:20:17 +00:00
Jean-Philippe Lang
c9ed3fdae3 updated CHANGELOG for 0.4.2 release
git-svn-id: http://redmine.rubyforge.org/svn/trunk@259 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 15:08:26 +00:00
Jean-Philippe Lang
7b164b5cd4 fixed: crash on my/page_layout (trying to modify a frozen hash)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@258 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 14:59:06 +00:00
Jean-Philippe Lang
dd54b1aacb fixed: hide mail preference not saved (my/account)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@257 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 13:56:35 +00:00
Jean-Philippe Lang
8fa96feb1f show "no data" label when there's nothing to display on project member list
git-svn-id: http://redmine.rubyforge.org/svn/trunk@256 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 13:45:15 +00:00
Jean-Philippe Lang
ddd0796e40 show "no data" label when there's nothing to display on changelog and roadmap
git-svn-id: http://redmine.rubyforge.org/svn/trunk@255 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 13:37:13 +00:00
Jean-Philippe Lang
4ef86b965b updated UPGRADING doc file
git-svn-id: http://redmine.rubyforge.org/svn/trunk@254 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 12:26:06 +00:00
Jean-Philippe Lang
1cc6dd871b updated documentation
git-svn-id: http://redmine.rubyforge.org/svn/trunk@253 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 12:13:24 +00:00
Jean-Philippe Lang
4564519a56 missing parenthesis added in filter.rb (net-ldap)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@252 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 11:45:55 +00:00
Jean-Philippe Lang
5a241fd12e file upload test now uses ActionController::TestUploadedFile
git-svn-id: http://redmine.rubyforge.org/svn/trunk@251 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 11:41:39 +00:00
Jean-Philippe Lang
840fcf2fa9 file upload test now uses ActionController::TestUploadedFile
git-svn-id: http://redmine.rubyforge.org/svn/trunk@250 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 11:41:36 +00:00
Jean-Philippe Lang
75e3ab737c replaced deprecated server_settings with smtp_settings
git-svn-id: http://redmine.rubyforge.org/svn/trunk@249 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 11:40:48 +00:00
Jean-Philippe Lang
516cedaa47 syntax error in rfpdf/makefont.rb
git-svn-id: http://redmine.rubyforge.org/svn/trunk@248 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-18 10:33:22 +00:00
Jean-Philippe Lang
3881ade96d removed some line breaks in application.css
git-svn-id: http://redmine.rubyforge.org/svn/trunk@247 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-05 20:18:22 +00:00
Jean-Philippe Lang
f4842d6eed added icons on my/page_layout top right links
git-svn-id: http://redmine.rubyforge.org/svn/trunk@246 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-05 19:48:01 +00:00
Jean-Philippe Lang
10e77d865b wrapped javascript with //<![CDATA[ in my/page_layout
git-svn-id: http://redmine.rubyforge.org/svn/trunk@245 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-05 19:40:26 +00:00
Jean-Philippe Lang
92725e5803 check that block is defined before rendering it (my/page_layout)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@244 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-05 19:38:19 +00:00
Jean-Philippe Lang
73510949ba check that block is defined before rendering it (my/page)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@243 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-05 19:36:21 +00:00
Jean-Philippe Lang
08ff4dfb21 removed underscores in block names (problem with scriptaculous sortables)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@242 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-05 19:33:43 +00:00
Jean-Philippe Lang
2e72f2eca8 updated prototype (1.50) and script.aculo.us javascripts
git-svn-id: http://redmine.rubyforge.org/svn/trunk@241 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-05 18:31:27 +00:00
Jean-Philippe Lang
9845bbddce mail notification removed for projects/roadmap in migration
git-svn-id: http://redmine.rubyforge.org/svn/trunk@240 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-05 18:20:39 +00:00
Jean-Philippe Lang
81b3ad5b87 updated documentation with new setting options
git-svn-id: http://redmine.rubyforge.org/svn/trunk@239 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 17:20:36 +00:00
Jean-Philippe Lang
6c4f196f6e removed strong tag for version name in settings view
git-svn-id: http://redmine.rubyforge.org/svn/trunk@238 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 17:18:16 +00:00
Jean-Philippe Lang
022b4ae57c rescued to_date exception when displaying a custom value
git-svn-id: http://redmine.rubyforge.org/svn/trunk@237 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 16:35:42 +00:00
Jean-Philippe Lang
d185e2f9e0 lost_password option checking in account controller
git-svn-id: http://redmine.rubyforge.org/svn/trunk@236 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 15:55:29 +00:00
Jean-Philippe Lang
2b7c31feb5 setting password_lost renamed to lost_password
git-svn-id: http://redmine.rubyforge.org/svn/trunk@235 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 15:54:56 +00:00
Jean-Philippe Lang
7dd312b1ac added a setting option to set max number of issues in export
git-svn-id: http://redmine.rubyforge.org/svn/trunk@234 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 15:45:38 +00:00
Jean-Philippe Lang
4ff7b395dd associations loading correction in projects/export_issues_pdf
git-svn-id: http://redmine.rubyforge.org/svn/trunk@233 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 12:27:41 +00:00
Jean-Philippe Lang
66044c620b issue list pdf export modified
git-svn-id: http://redmine.rubyforge.org/svn/trunk@232 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 12:24:16 +00:00
Jean-Philippe Lang
52c1718ee8 added a setting option to disable "password lost" functionality
git-svn-id: http://redmine.rubyforge.org/svn/trunk@231 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 09:37:28 +00:00
Jean-Philippe Lang
8b180aa606 removed an unused localization string
git-svn-id: http://redmine.rubyforge.org/svn/trunk@230 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 09:23:28 +00:00
Jean-Philippe Lang
ccaf6c8df0 removed unused development_* environments
git-svn-id: http://redmine.rubyforge.org/svn/trunk@229 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 09:20:07 +00:00
Jean-Philippe Lang
879a614cde added roadmap view
git-svn-id: http://redmine.rubyforge.org/svn/trunk@228 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 09:18:40 +00:00
Jean-Philippe Lang
8c3dc34359 rightbox class set to display:none for printing
git-svn-id: http://redmine.rubyforge.org/svn/trunk@227 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-04 09:08:49 +00:00
Jean-Philippe Lang
f82654f158 Title property added for pdf export of an issue
git-svn-id: http://redmine.rubyforge.org/svn/trunk@226 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-03 14:12:28 +00:00
Jean-Philippe Lang
c365614548 Title property added for generated pdf gantt
git-svn-id: http://redmine.rubyforge.org/svn/trunk@225 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-03 14:08:47 +00:00
Jean-Philippe Lang
a3c2c4a48a Creator property added for generated pdf files
git-svn-id: http://redmine.rubyforge.org/svn/trunk@224 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-03 14:00:22 +00:00
Jean-Philippe Lang
8316e78667 custom_field.possible_values is now serialized (no longer pipe separated)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@223 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-03 12:57:33 +00:00
Jean-Philippe Lang
4a988b0f92 removed translation of error messages inside ActiveRecord module
git-svn-id: http://redmine.rubyforge.org/svn/trunk@222 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-03 12:42:06 +00:00
Jean-Philippe Lang
b5e80bf90f filter is now cleared when clicking on 'Issues' menu item
git-svn-id: http://redmine.rubyforge.org/svn/trunk@221 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 16:13:45 +00:00
Jean-Philippe Lang
da426fa652 added a limit of 500 issues when exporting to csv or pdf
git-svn-id: http://redmine.rubyforge.org/svn/trunk@220 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 16:05:54 +00:00
Jean-Philippe Lang
39e65a41a2 added tests for settings
git-svn-id: http://redmine.rubyforge.org/svn/trunk@219 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 15:38:34 +00:00
Jean-Philippe Lang
1eb17b08f9 added parentheses to get rid of warning
git-svn-id: http://redmine.rubyforge.org/svn/trunk@218 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 15:22:07 +00:00
Jean-Philippe Lang
318c8717b8 empty tokens table
git-svn-id: http://redmine.rubyforge.org/svn/trunk@217 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 15:20:49 +00:00
Jean-Philippe Lang
7184632b84 fixtures loading correction
git-svn-id: http://redmine.rubyforge.org/svn/trunk@216 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 15:16:30 +00:00
Jean-Philippe Lang
1e4a7d55e0 added unit tests for mailer
git-svn-id: http://redmine.rubyforge.org/svn/trunk@215 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 14:47:40 +00:00
Jean-Philippe Lang
5101c55e10 added lang files validition test
git-svn-id: http://redmine.rubyforge.org/svn/trunk@214 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 14:47:13 +00:00
Jean-Philippe Lang
c1537b5291 * fixed a variable name error in Setting
* setting values to_s


git-svn-id: http://redmine.rubyforge.org/svn/trunk@213 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 14:28:54 +00:00
Jean-Philippe Lang
4c767d636a removed broken route for sorting links
git-svn-id: http://redmine.rubyforge.org/svn/trunk@212 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 13:57:36 +00:00
Jean-Philippe Lang
aa91ca0a8d issue list: added 'Priority' column, removed 'Created on' column
git-svn-id: http://redmine.rubyforge.org/svn/trunk@211 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-02-02 13:56:49 +00:00
Jean-Philippe Lang
d3b831bf7b post method verification for trackers/move
git-svn-id: http://redmine.rubyforge.org/svn/trunk@210 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-31 21:20:49 +00:00
Jean-Philippe Lang
fa688d48e6 added the ability to set the sort order for trackers
git-svn-id: http://redmine.rubyforge.org/svn/trunk@209 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-31 21:18:43 +00:00
Jean-Philippe Lang
671a0fa101 added the ability to set the sort order for roles
git-svn-id: http://redmine.rubyforge.org/svn/trunk@208 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-31 20:57:01 +00:00
Jean-Philippe Lang
99f006f2c9 removed png transparency (not supported in ie)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@207 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-31 20:25:24 +00:00
Jean-Philippe Lang
f9c400a727 custom fields list screen split in 3 tabs (one for each kind of custom fields)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@206 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-31 20:10:21 +00:00
Jean-Philippe Lang
fe22797d69 added the ability to set the sort order for issue statuses
git-svn-id: http://redmine.rubyforge.org/svn/trunk@205 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-31 19:53:24 +00:00
Jean-Philippe Lang
d29ba0b80f updated css for online help
git-svn-id: http://redmine.rubyforge.org/svn/trunk@204 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-29 18:45:33 +00:00
Jean-Philippe Lang
18fd46ab6b fixed french issue_edit mail template
git-svn-id: http://redmine.rubyforge.org/svn/trunk@203 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-28 19:59:39 +00:00
Jean-Philippe Lang
ec7ac956e4 removed environment information
git-svn-id: http://redmine.rubyforge.org/svn/trunk@202 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-28 19:54:41 +00:00
Jean-Philippe Lang
99c560295f indentation corrections
git-svn-id: http://redmine.rubyforge.org/svn/trunk@201 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-28 00:00:21 +00:00
Jean-Philippe Lang
90c7cf9763 proper language setting for mail notifications
git-svn-id: http://redmine.rubyforge.org/svn/trunk@200 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-27 23:22:58 +00:00
Jean-Philippe Lang
3dc9ceaadf credits for english help translation to Todd McGrath
git-svn-id: http://redmine.rubyforge.org/svn/trunk@199 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-27 22:48:43 +00:00
Jean-Philippe Lang
23f6185bfe updated changelog and doc files
git-svn-id: http://redmine.rubyforge.org/svn/trunk@198 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-27 22:35:58 +00:00
Jean-Philippe Lang
1cb0294388 added unit tests for issue statuses, user preferences and tokens
git-svn-id: http://redmine.rubyforge.org/svn/trunk@197 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-27 22:31:42 +00:00
Jean-Philippe Lang
2d47a6d71c mail notifications added when:
* a document is added
* a file is added to the project
* an attachment is added to an issue or a document

git-svn-id: http://redmine.rubyforge.org/svn/trunk@196 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-27 15:01:19 +00:00
Jean-Philippe Lang
22c2209cf9 redmine_demo.db added to svn:ignored
git-svn-id: http://redmine.rubyforge.org/svn/trunk@195 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-27 12:32:39 +00:00
Jean-Philippe Lang
471679b0f0 deprecated @headers replaced
git-svn-id: http://redmine.rubyforge.org/svn/trunk@194 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-27 09:25:55 +00:00
Jean-Philippe Lang
862c9d76e6 smaller footer font
git-svn-id: http://redmine.rubyforge.org/svn/trunk@193 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-27 09:23:00 +00:00
Jean-Philippe Lang
2c187c43bf fixed: filters ignored when exporting a predefined query to csv/pdf
git-svn-id: http://redmine.rubyforge.org/svn/trunk@192 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 22:05:32 +00:00
Jean-Philippe Lang
486b4e9ea2 deprecated ":post => true" replaced
git-svn-id: http://redmine.rubyforge.org/svn/trunk@191 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 21:09:27 +00:00
Jean-Philippe Lang
5f361e71df only active users are now proposed when adding a member to a project
git-svn-id: http://redmine.rubyforge.org/svn/trunk@190 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 20:52:52 +00:00
Jean-Philippe Lang
13881f5a5b deprecated projects_count replaced
git-svn-id: http://redmine.rubyforge.org/svn/trunk@189 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 20:41:16 +00:00
Jean-Philippe Lang
c38a2112c6 deprecated children_count replaced
git-svn-id: http://redmine.rubyforge.org/svn/trunk@188 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 20:34:09 +00:00
Jean-Philippe Lang
a9fc777b20 removed space before argument parentheses
git-svn-id: http://redmine.rubyforge.org/svn/trunk@187 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 20:24:51 +00:00
Jean-Philippe Lang
ab15456119 deprecated count call modified
git-svn-id: http://redmine.rubyforge.org/svn/trunk@186 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 20:06:05 +00:00
Jean-Philippe Lang
0d55613359 replaced deprecated human_size by number_to_human_size
git-svn-id: http://redmine.rubyforge.org/svn/trunk@185 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 20:02:49 +00:00
Jean-Philippe Lang
845460b165 deprecated start_form_tag replaced by form_tag
git-svn-id: http://redmine.rubyforge.org/svn/trunk@184 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 19:56:25 +00:00
Jean-Philippe Lang
7c27fb7c1d fixed: crash when changing the status of an issue
git-svn-id: http://redmine.rubyforge.org/svn/trunk@183 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 18:55:02 +00:00
Jean-Philippe Lang
e51c20c496 project settings tabs redesign
git-svn-id: http://redmine.rubyforge.org/svn/trunk@182 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 18:27:10 +00:00
Jean-Philippe Lang
190fef513f * project settings split in 4 tabs
* prototype.js upgraded to 1.5.0_rc1

git-svn-id: http://redmine.rubyforge.org/svn/trunk@181 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 17:59:06 +00:00
Jean-Philippe Lang
b9ef10fe3f fixed: unable to delete an issue status even if it's not used yet
git-svn-id: http://redmine.rubyforge.org/svn/trunk@180 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 17:50:48 +00:00
Jean-Philippe Lang
2b9777555f fixed: setting an issue status as default status leads to an sql error with SQLite
git-svn-id: http://redmine.rubyforge.org/svn/trunk@179 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-26 17:39:36 +00:00
Jean-Philippe Lang
1f79394ac4 updated date removed from my/account view (useless since account is updated at each login)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@178 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-25 19:35:39 +00:00
Jean-Philippe Lang
e2e111f95e * added missing fields to csv export: priority, start date, due date, done ratio
git-svn-id: http://redmine.rubyforge.org/svn/trunk@177 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-25 19:32:07 +00:00
Jean-Philippe Lang
8985d05a66 mongrel_debug unversioned
git-svn-id: http://redmine.rubyforge.org/svn/trunk@176 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-25 18:28:54 +00:00
Jean-Philippe Lang
4e03668eec * replaced :controller => '' broken statements by :controller => 'welcome'
* request_uri method no more used

git-svn-id: http://redmine.rubyforge.org/svn/trunk@175 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-25 18:27:42 +00:00
Jean-Philippe Lang
2789b08dd0 removed serialize class_name option in user_preference
git-svn-id: http://redmine.rubyforge.org/svn/trunk@174 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-25 18:25:57 +00:00
Jean-Philippe Lang
66a02688ad Modified GLoc helpers to ensure compatibility with rails 1.2
git-svn-id: http://redmine.rubyforge.org/svn/trunk@173 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-24 18:15:27 +00:00
Jean-Philippe Lang
681bbf02ae removed "selected" class on Home menu item
git-svn-id: http://redmine.rubyforge.org/svn/trunk@172 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-21 16:52:32 +00:00
Jean-Philippe Lang
c80de840d1 updated online help with settings description
git-svn-id: http://redmine.rubyforge.org/svn/trunk@171 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-21 14:39:50 +00:00
Jean-Philippe Lang
bd3458da6e added Redmine::VERSION module
git-svn-id: http://redmine.rubyforge.org/svn/trunk@170 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-21 12:54:51 +00:00
Jean-Philippe Lang
4ccbc65628 added translated strings for settings view
git-svn-id: http://redmine.rubyforge.org/svn/trunk@169 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-21 12:31:16 +00:00
Jean-Philippe Lang
9a2753931b added missing string en de, en, es
git-svn-id: http://redmine.rubyforge.org/svn/trunk@168 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-21 11:56:20 +00:00
Jean-Philippe Lang
0b4d4db131 settings are now stored in the database (config_custom.rb no more used) and editable through the application in: Admin -> Settings
git-svn-id: http://redmine.rubyforge.org/svn/trunk@167 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-21 11:50:22 +00:00
Jean-Philippe Lang
a1b12335ab 'new query' link moved
git-svn-id: http://redmine.rubyforge.org/svn/trunk@166 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-19 17:23:47 +00:00
Jean-Philippe Lang
a8137d5d17 added back "fixed version" in issue/show and filters
git-svn-id: http://redmine.rubyforge.org/svn/trunk@165 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-15 20:22:23 +00:00
Jean-Philippe Lang
1e5362b1f7 added package icon on changelog
git-svn-id: http://redmine.rubyforge.org/svn/trunk@164 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-15 20:14:06 +00:00
Jean-Philippe Lang
51ea8b0295 tooltips added on calendar
git-svn-id: http://redmine.rubyforge.org/svn/trunk@161 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-13 10:36:18 +00:00
Jean-Philippe Lang
f35194e604 tooltips added on Gantt chart to view the details of the issues
(added csshover behaviour to make it work under IE)

git-svn-id: http://redmine.rubyforge.org/svn/trunk@160 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-09 21:27:21 +00:00
Jean-Philippe Lang
3ef57c1ac3 folder icon replaced
git-svn-id: http://redmine.rubyforge.org/svn/trunk@159 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-08 19:56:47 +00:00
Jean-Philippe Lang
69b7f9e9a2 folder icon removed
git-svn-id: http://redmine.rubyforge.org/svn/trunk@158 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-08 19:56:16 +00:00
Jean-Philippe Lang
220641909c * all icons replaced (new icons are based on GPL icon set: "KDE Crystal Diamond 2.5" -by paolino- and "kNeu! Alpha v0.1" -by Pablo Fabregat-)
* fixed: subprojects count is always 0 on projects list

git-svn-id: http://redmine.rubyforge.org/svn/trunk@157 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-08 19:21:59 +00:00
Jean-Philippe Lang
31bc6054a3 replaced details.png by zoom_in.png on reports
git-svn-id: http://redmine.rubyforge.org/svn/trunk@156 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-06 14:28:08 +00:00
Jean-Philippe Lang
94391723c0 added a button on users/list to manually activate an account
git-svn-id: http://redmine.rubyforge.org/svn/trunk@155 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-06 14:22:22 +00:00
Jean-Philippe Lang
5fd3decb16 added "auto" option for user's language (browser based)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@154 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-06 14:11:28 +00:00
Jean-Philippe Lang
d7c015a884 removed "add a comment" h3
git-svn-id: http://redmine.rubyforge.org/svn/trunk@153 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-06 12:47:20 +00:00
Jean-Philippe Lang
8ed55e8d7a added total number of issues per tracker on projects/show
git-svn-id: http://redmine.rubyforge.org/svn/trunk@152 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-06 12:18:29 +00:00
Jean-Philippe Lang
979892a109 calendar javascripts and stylesheets removed from base layout. they're now only added to html header when needed.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@151 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-06 09:08:17 +00:00
Jean-Philippe Lang
776d5ce554 XHTML compliance improvements
git-svn-id: http://redmine.rubyforge.org/svn/trunk@150 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-05 19:10:57 +00:00
Jean-Philippe Lang
28ea323791 updated RDM_APP_VERSION for 0.4.1
git-svn-id: http://redmine.rubyforge.org/svn/trunk@148 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-03 18:38:08 +00:00
Jean-Philippe Lang
18787caab9 0.4.1 release
git-svn-id: http://redmine.rubyforge.org/svn/trunk@147 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-03 18:32:03 +00:00
Jean-Philippe Lang
390d6023c6 * added calendar.png removed by accident
* removed resizer background style for textareas

git-svn-id: http://redmine.rubyforge.org/svn/trunk@146 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-03 18:29:16 +00:00
Jean-Philippe Lang
e1ef9a5c72 fixed: no recipient if one of the members of the project has disabled mail notifications
git-svn-id: http://redmine.rubyforge.org/svn/trunk@145 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-03 18:26:45 +00:00
Jean-Philippe Lang
f3babef54a 0.4.0 release
git-svn-id: http://redmine.rubyforge.org/svn/trunk@143 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 16:34:15 +00:00
Jean-Philippe Lang
2dc3850798 added an icon on news comments
git-svn-id: http://redmine.rubyforge.org/svn/trunk@142 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 15:27:10 +00:00
Jean-Philippe Lang
18001e5a5b various documentation updates
git-svn-id: http://redmine.rubyforge.org/svn/trunk@141 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 14:56:10 +00:00
Jean-Philippe Lang
32f6cb7c13 unused images cleaning
git-svn-id: http://redmine.rubyforge.org/svn/trunk@140 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 11:20:10 +00:00
Jean-Philippe Lang
9f76b4d2ef enumerations/list redesign
git-svn-id: http://redmine.rubyforge.org/svn/trunk@139 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 11:15:54 +00:00
Jean-Philippe Lang
a9efe82117 updated redirection to the help main index (recognition fails when redirecting to a directory)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@138 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 10:49:59 +00:00
Jean-Philippe Lang
4ee55dc456 updated validation format of repository url to allow file:///
git-svn-id: http://redmine.rubyforge.org/svn/trunk@137 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 10:12:15 +00:00
Jean-Philippe Lang
470ef4d11e * replaced "add_issue" links on projects/show by a drop down list
* added this shortcut on list_issues

git-svn-id: http://redmine.rubyforge.org/svn/trunk@136 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 09:58:07 +00:00
Jean-Philippe Lang
57d4e698fe updated notice_file_not_found message
git-svn-id: http://redmine.rubyforge.org/svn/trunk@135 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 08:49:23 +00:00
Jean-Philippe Lang
f50544bb15 addded ruby-net-ldap (0.0.4) dependency in vendor/pluggin
git-svn-id: http://redmine.rubyforge.org/svn/trunk@134 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 08:48:40 +00:00
Jean-Philippe Lang
e3becc7c3c ActiveRecord::RecordNotFound exceptions handled more gracefully
git-svn-id: http://redmine.rubyforge.org/svn/trunk@133 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-02 08:47:07 +00:00
Jean-Philippe Lang
e7caec6e7d language for default configuration data can now be chosen when running 'load_default_data' task
git-svn-id: http://redmine.rubyforge.org/svn/trunk@132 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-01 21:34:10 +00:00
Jean-Philippe Lang
6487c1803f option to set maximum size of uploaded files
git-svn-id: http://redmine.rubyforge.org/svn/trunk@131 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-01 12:09:09 +00:00
Jean-Philippe Lang
ff65a5b22a added multiple file upload for documents and files modules
git-svn-id: http://redmine.rubyforge.org/svn/trunk@130 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-01 11:26:56 +00:00
Jean-Philippe Lang
7a03cf92ba fixed: non public projects were shown on welcome screen even if current user is not a member
git-svn-id: http://redmine.rubyforge.org/svn/trunk@129 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-01-01 10:13:01 +00:00
Jean-Philippe Lang
e6fa690d65 fixed: public actions not authorized for members of non public projects
git-svn-id: http://redmine.rubyforge.org/svn/trunk@128 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-31 17:00:16 +00:00
Jean-Philippe Lang
95cc65f14e replaced deprecated controller instance variables: @params, @session, @request
git-svn-id: http://redmine.rubyforge.org/svn/trunk@127 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 21:33:44 +00:00
Jean-Philippe Lang
b3a3d3e2fa replaced deprecated find_all calls
git-svn-id: http://redmine.rubyforge.org/svn/trunk@126 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 21:18:44 +00:00
Jean-Philippe Lang
0820e745d6 textile for revisions comments
git-svn-id: http://redmine.rubyforge.org/svn/trunk@125 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 21:15:28 +00:00
Jean-Philippe Lang
2197fa3120 added issues integration tests
git-svn-id: http://redmine.rubyforge.org/svn/trunk@124 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 20:14:03 +00:00
Jean-Philippe Lang
b4d4b80dcd replaced deprecated ":dependent => true" statements
git-svn-id: http://redmine.rubyforge.org/svn/trunk@123 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 17:11:44 +00:00
Jean-Philippe Lang
3bfaa20c05 fixed: unable to attach a file when creating an issue ("attachment: invalid" error)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@122 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 17:10:05 +00:00
Jean-Philippe Lang
58f8a23d58 * news rss feed added
* "header_tags" block added to allow inclusion of page specific tags in the html header (stylesheets, javascripts, feeds...)

git-svn-id: http://redmine.rubyforge.org/svn/trunk@121 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 16:19:12 +00:00
Jean-Philippe Lang
1f3380bfad misc GUI changes on roles views
git-svn-id: http://redmine.rubyforge.org/svn/trunk@120 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 15:02:33 +00:00
Jean-Philippe Lang
451ec23060 replaced some submit buttons by links on projects/settings
git-svn-id: http://redmine.rubyforge.org/svn/trunk@119 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 11:42:37 +00:00
Jean-Philippe Lang
4c84165aa0 added the ability to manage users memberships directly on users/edit (administration module)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@118 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 11:28:22 +00:00
Jean-Philippe Lang
a6c8feea21 misc GUI modifications
git-svn-id: http://redmine.rubyforge.org/svn/trunk@117 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 10:11:55 +00:00
Jean-Philippe Lang
718de6c7fd added a condition on project -> members association so that only active users are considered as members
git-svn-id: http://redmine.rubyforge.org/svn/trunk@116 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 09:13:56 +00:00
Jean-Philippe Lang
d81a135704 href title attribute with full issue subject added
git-svn-id: http://redmine.rubyforge.org/svn/trunk@115 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 09:13:03 +00:00
Jean-Philippe Lang
1a90fbee8b fixed a bug in gantt display when last day is a monday
git-svn-id: http://redmine.rubyforge.org/svn/trunk@114 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-26 09:12:13 +00:00
Jean-Philippe Lang
2ac30707d2 updated the appearance of table headers
git-svn-id: http://redmine.rubyforge.org/svn/trunk@113 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-25 10:53:15 +00:00
Jean-Philippe Lang
58a36e3604 attachments list on issues/show:
* "delete" form replaced by link_to
* added css class for attachment icon 

git-svn-id: http://redmine.rubyforge.org/svn/trunk@112 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-25 10:14:24 +00:00
Jean-Philippe Lang
676fe403ab removed menu.css and rails.css (content merged into application.css)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@111 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-25 09:56:21 +00:00
Jean-Philippe Lang
13611bf0ab route for repositories controller removed (problem when running under apache)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@110 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-24 17:19:40 +00:00
Jean-Philippe Lang
ad02b3fb7b fixed in svn browser: revisions were ignored when no author was found
git-svn-id: http://redmine.rubyforge.org/svn/trunk@109 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-24 17:18:29 +00:00
Jean-Philippe Lang
d3600e729f css cleaning
git-svn-id: http://redmine.rubyforge.org/svn/trunk@108 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-24 16:35:25 +00:00
Jean-Philippe Lang
6c8e1514aa xss in issue subject on issues/edit
git-svn-id: http://redmine.rubyforge.org/svn/trunk@107 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-24 15:41:23 +00:00
Jean-Philippe Lang
bc44158501 svn browser merged in trunk
git-svn-id: http://redmine.rubyforge.org/svn/trunk@106 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-24 13:38:45 +00:00
Jean-Philippe Lang
918123cd06 * code and views cleaning
* javascript added on custom field form to show/hide fields according to the format of custom field

git-svn-id: http://redmine.rubyforge.org/svn/trunk@100 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-17 14:22:09 +00:00
Jean-Philippe Lang
2b86ef8e28 various modifications to prevent xss
- validation of names and labels against /^[\w\s\'\-]*$/i
- html entities encoding

git-svn-id: http://redmine.rubyforge.org/svn/trunk@99 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-17 08:10:18 +00:00
Jean-Philippe Lang
3e28dc669b various eager loadings added
git-svn-id: http://redmine.rubyforge.org/svn/trunk@98 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-16 17:33:31 +00:00
Jean-Philippe Lang
bee3f353fc fixed bug when no version is selected in projects/add_file
git-svn-id: http://redmine.rubyforge.org/svn/trunk@97 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-16 16:31:11 +00:00
Jean-Philippe Lang
005f4baaa4 issues table is no more displayed if there is no issue to display
git-svn-id: http://redmine.rubyforge.org/svn/trunk@96 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-16 13:45:56 +00:00
Jean-Philippe Lang
2b0142580f "queries" branch merged
git-svn-id: http://redmine.rubyforge.org/svn/trunk@95 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-16 13:37:32 +00:00
Jean-Philippe Lang
236c735d08 contextual links redesign
git-svn-id: http://redmine.rubyforge.org/svn/trunk@93 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-16 12:15:31 +00:00
Jean-Philippe Lang
e5562afcd3 useless javascript for drop down menu removed
git-svn-id: http://redmine.rubyforge.org/svn/trunk@85 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-13 19:57:19 +00:00
Jean-Philippe Lang
256eb6250e bug fixed in projects/activity due to sql join
documents added in projects/activity

git-svn-id: http://redmine.rubyforge.org/svn/trunk@84 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-11 21:25:50 +00:00
Jean-Philippe Lang
e50ba150c3 added print.css to hide header, menus and footer
git-svn-id: http://redmine.rubyforge.org/svn/trunk@83 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-10 20:34:51 +00:00
Jean-Philippe Lang
bab9c40dcc "export to" label added on issues/show
git-svn-id: http://redmine.rubyforge.org/svn/trunk@82 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-10 20:18:13 +00:00
Jean-Philippe Lang
55ed70529a added model Comment.
comments can now be added on news.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@81 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-10 18:35:48 +00:00
Jean-Philippe Lang
28c6aa4e6d css adjustment for drag n drop handles
git-svn-id: http://redmine.rubyforge.org/svn/trunk@74 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-07 18:12:27 +00:00
Jean-Philippe Lang
ab88b27622 gantt link added in left menu and removed from calendar view
git-svn-id: http://redmine.rubyforge.org/svn/trunk@73 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-06 21:13:46 +00:00
Jean-Philippe Lang
2c335dbf32 calendar and activity views edited (previous/next links)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@72 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-06 20:54:43 +00:00
Jean-Philippe Lang
d6d1502200 blockquote style added in css
git-svn-id: http://redmine.rubyforge.org/svn/trunk@69 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-05 21:06:07 +00:00
Jean-Philippe Lang
4bb61ade27 /trunk/redmine removed
git-svn-id: http://redmine.rubyforge.org/svn/trunk@68 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-05 20:46:55 +00:00
Jean-Philippe Lang
96f83cc8f0 trunk moved from /trunk/redmine to /trunk
git-svn-id: http://redmine.rubyforge.org/svn/trunk@67 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-05 20:45:04 +00:00
Jean-Philippe Lang
eabc04d836 form_for added in my/account view
git-svn-id: http://redmine.rubyforge.org/svn/trunk@66 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-04 22:02:30 +00:00
Jean-Philippe Lang
b3be8745b0 tr color removed on issues list
git-svn-id: http://redmine.rubyforge.org/svn/trunk@65 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-04 21:31:14 +00:00
Jean-Philippe Lang
aa28c3d7ba git-svn-id: http://redmine.rubyforge.org/svn/trunk@64 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-12-04 21:05:17 +00:00
Jean-Philippe Lang
948e2190f8 "hide my email address" preference added, so that it's not displayed on account/show
git-svn-id: http://redmine.rubyforge.org/svn/trunk@63 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-03 20:51:17 +00:00
Jean-Philippe Lang
362633d486 - new controller "myController"
- account/my_page moved to my/page
- account/my_account mmoved to my/account
- "my page" is now customizable (table user_preferences added)

git-svn-id: http://redmine.rubyforge.org/svn/trunk@62 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-12-03 19:55:45 +00:00
Jean-Philippe Lang
120e39ba80 news and documents views modified
git-svn-id: http://redmine.rubyforge.org/svn/trunk@61 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-30 22:17:44 +00:00
Jean-Philippe Lang
98d4bdb7df documents views modified
git-svn-id: http://redmine.rubyforge.org/svn/trunk@60 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-30 22:00:35 +00:00
Jean-Philippe Lang
2c6e3cb02d export links modified
git-svn-id: http://redmine.rubyforge.org/svn/trunk@59 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-29 21:50:10 +00:00
Jean-Philippe Lang
9c70084ea5 legend added on calendar
git-svn-id: http://redmine.rubyforge.org/svn/trunk@58 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-29 20:29:12 +00:00
Jean-Philippe Lang
9b2bd72e1f issue subjects modified on gantt pdf export
git-svn-id: http://redmine.rubyforge.org/svn/trunk@57 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-29 20:06:44 +00:00
Jean-Philippe Lang
707360169e issue links modified on activity, calendar and gantt views
git-svn-id: http://redmine.rubyforge.org/svn/trunk@56 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-29 20:02:55 +00:00
Jean-Philippe Lang
418b8d861a mailer bug fix
git-svn-id: http://redmine.rubyforge.org/svn/trunk@55 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-27 22:45:10 +00:00
Jean-Philippe Lang
42181112ff improved issues change history
git-svn-id: http://redmine.rubyforge.org/svn/trunk@54 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-27 22:31:14 +00:00
Jean-Philippe Lang
67e81b0ae9 gantt correction
git-svn-id: http://redmine.rubyforge.org/svn/trunk@53 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-27 19:53:59 +00:00
Jean-Philippe Lang
51317b350c git-svn-id: http://redmine.rubyforge.org/svn/trunk@52 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-11-21 22:39:46 +00:00
Jean-Philippe Lang
c83e794871 git-svn-id: http://redmine.rubyforge.org/svn/trunk@51 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-11-21 22:27:47 +00:00
Jean-Philippe Lang
26ec775854 git-svn-id: http://redmine.rubyforge.org/svn/trunk@50 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-11-21 19:09:40 +00:00
Jean-Philippe Lang
5e9e01bf7f missing rfpdf in the repository...
git-svn-id: http://redmine.rubyforge.org/svn/trunk@49 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-21 18:34:04 +00:00
Jean-Philippe Lang
f7df1b7d55 missing rfpdf in the repository...
git-svn-id: http://redmine.rubyforge.org/svn/trunk@48 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-21 18:33:16 +00:00
Jean-Philippe Lang
abb5d019cd git-svn-id: http://redmine.rubyforge.org/svn/trunk@47 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-11-20 22:41:27 +00:00
Jean-Philippe Lang
474b5a52d6 git-svn-id: http://redmine.rubyforge.org/svn/trunk@46 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-11-20 20:40:52 +00:00
Jean-Philippe Lang
63d3b12bb5 * css modified
* 404 and 500 error pages modified

git-svn-id: http://redmine.rubyforge.org/svn/trunk@45 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-17 20:24:34 +00:00
Jean-Philippe Lang
7136b85f21 * new report: project activity
* "start date" and "% done" fields added on issues
* project calendar added
* gantt chart added (exportable to pdf)
* multiple file upload for issues attachments
* user custom field displayed on account/show
* default configuration improved (default roles, trackers, status, permissions and workflows)
* fixed: project settings now displayed according to user's permissions

git-svn-id: http://redmine.rubyforge.org/svn/trunk@44 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-12 18:50:30 +00:00
Jean-Philippe Lang
6707034768 english help translation added
thx to Karim Trott

git-svn-id: http://redmine.rubyforge.org/svn/trunk@43 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-07 17:44:50 +00:00
Jean-Philippe Lang
ef99d3c4ce english help translation added
thx to Karim Trott

git-svn-id: http://redmine.rubyforge.org/svn/trunk@42 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-07 17:44:47 +00:00
Jean-Philippe Lang
4c9f27e550 git-svn-id: http://redmine.rubyforge.org/svn/trunk@41 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-11-05 20:31:29 +00:00
Jean-Philippe Lang
55dded8e5f multiple file upload
git-svn-id: http://redmine.rubyforge.org/svn/trunk@40 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-11-05 18:38:20 +00:00
Jean-Philippe Lang
0778ac8c1b git-svn-id: http://redmine.rubyforge.org/svn/trunk@39 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-11-05 16:52:22 +00:00
Jean-Philippe Lang
3628515b31 git-svn-id: http://redmine.rubyforge.org/svn/trunk@38 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-11-05 16:49:27 +00:00
Jean-Philippe Lang
51e0989c49 * single/multiple issues pdf export added
* new filter in issues list: "Author"
* option to set number of results per page on issues list
* localized csv separator (comma/semicolon)
* csv output encoded to ISO-8859-1
* fixed: custom fields not in csv exports

git-svn-id: http://redmine.rubyforge.org/svn/trunk@37 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-10-22 14:47:25 +00:00
Jean-Philippe Lang
79cbe8d199 issues/add_note added
git-svn-id: http://redmine.rubyforge.org/svn/trunk@36 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-10-21 16:07:34 +00:00
Jean-Philippe Lang
a2d4ca095a issues report by author
git-svn-id: http://redmine.rubyforge.org/svn/trunk@35 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-10-21 15:41:42 +00:00
Jean-Philippe Lang
7473be4072 issues reports improvements
git-svn-id: http://redmine.rubyforge.org/svn/trunk@34 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-10-21 12:57:19 +00:00
Jean-Philippe Lang
6a0022d7a1 ajaxified paginators
git-svn-id: http://redmine.rubyforge.org/svn/trunk@33 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-10-21 10:38:53 +00:00
Jean-Philippe Lang
e4d4a12c6a git-svn-id: http://redmine.rubyforge.org/svn/trunk@32 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-10-15 14:33:04 +00:00
Jean-Philippe Lang
4a1cfb3df9 git-svn-id: http://redmine.rubyforge.org/svn/trunk@31 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-10-15 09:00:05 +00:00
Jean-Philippe Lang
b00769f606 git-svn-id: http://redmine.rubyforge.org/svn/trunk@30 e93f8b46-1217-0410-a6f0-8f06a7374b81 2006-10-14 07:47:25 +00:00
Jean-Philippe Lang
6e367354e9 date picker
git-svn-id: http://redmine.rubyforge.org/svn/trunk@29 e93f8b46-1217-0410-a6f0-8f06a7374b81
2006-10-14 07:44:00 +00:00
864 changed files with 41072 additions and 10984 deletions

25
app/apis/sys_api.rb Normal file
View File

@@ -0,0 +1,25 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class SysApi < ActionWebService::API::Base
api_method :projects,
:expects => [],
:returns => [[Project]]
api_method :repository_created,
:expects => [:int, :string],
:returns => [:int]
end

View File

@@ -1,165 +1,131 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AccountController < ApplicationController
layout 'base'
helper :custom_fields
include CustomFieldsHelper
# prevents login action to be filtered by check_if_login_required application scope filter
skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register]
before_filter :require_login, :except => [:show, :login, :lost_password, :register]
# Show user's account
def show
@user = User.find(params[:id])
end
# Login request and validation
def login
if request.get?
# Logout user
self.logged_in_user = nil
else
# Authenticate user
user = User.try_to_login(params[:login], params[:password])
if user
self.logged_in_user = user
redirect_back_or_default :controller => 'account', :action => 'my_page'
else
flash.now[:notice] = l(:notice_account_invalid_creditentials)
end
end
end
# Log out current user and redirect to welcome page
def logout
self.logged_in_user = nil
redirect_to :controller => ''
end
# Show logged in user's page
def my_page
@user = self.logged_in_user
@reported_issues = Issue.find(:all, :conditions => ["author_id=?", @user.id], :limit => 10, :include => [ :status, :project, :tracker ], :order => 'issues.updated_on DESC')
@assigned_issues = Issue.find(:all, :conditions => ["assigned_to_id=?", @user.id], :limit => 10, :include => [ :status, :project, :tracker ], :order => 'issues.updated_on DESC')
end
# Edit logged in user's account
def my_account
@user = self.logged_in_user
if request.post? and @user.update_attributes(@params[:user])
set_localization
flash.now[:notice] = l(:notice_account_updated)
self.logged_in_user.reload
end
end
# Change logged in user's password
def change_password
@user = self.logged_in_user
flash[:notice] = l(:notice_can_t_change_password) and redirect_to :action => 'my_account' and return if @user.auth_source_id
if @user.check_password?(@params[:password])
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if @user.save
flash[:notice] = l(:notice_account_password_updated)
else
render :action => 'my_account'
return
end
else
flash[:notice] = l(:notice_account_wrong_password)
end
redirect_to :action => 'my_account'
end
# Enable user to choose a new password
def lost_password
if params[:token]
@token = Token.find_by_action_and_value("recovery", params[:token])
redirect_to :controller => '' and return unless @token and !@token.expired?
@user = @token.user
if request.post?
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if @user.save
@token.destroy
flash[:notice] = l(:notice_account_password_updated)
redirect_to :action => 'login'
return
end
end
render :template => "account/password_recovery"
return
else
if request.post?
user = User.find_by_mail(params[:mail])
# user not found in db
flash.now[:notice] = l(:notice_account_unknown_email) and return unless user
# user uses an external authentification
flash.now[:notice] = l(:notice_can_t_change_password) and return if user.auth_source_id
# create a new token for password recovery
token = Token.new(:user => user, :action => "recovery")
if token.save
# send token to user via email
Mailer.set_language_if_valid(user.language)
Mailer.deliver_lost_password(token)
flash[:notice] = l(:notice_account_lost_email_sent)
redirect_to :action => 'login'
return
end
end
end
end
# User self-registration
def register
redirect_to :controller => '' and return if $RDM_SELF_REGISTRATION == false
if params[:token]
token = Token.find_by_action_and_value("register", params[:token])
redirect_to :controller => '' and return unless token and !token.expired?
user = token.user
redirect_to :controller => '' and return unless user.status == User::STATUS_REGISTERED
user.status = User::STATUS_ACTIVE
if user.save
token.destroy
flash[:notice] = l(:notice_account_activated)
redirect_to :action => 'login'
return
end
else
if request.get?
@user = User.new(:language => $RDM_DEFAULT_LANG)
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
else
@user = User.new(params[:user])
@user.admin = false
@user.login = params[:user][:login]
@user.status = User::STATUS_REGISTERED
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values
token = Token.new(:user => @user, :action => "register")
if @user.save and token.save
Mailer.set_language_if_valid(@user.language)
Mailer.deliver_register(token)
flash[:notice] = l(:notice_account_register_done)
redirect_to :controller => ''
end
end
end
end
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AccountController < ApplicationController
layout 'base'
helper :custom_fields
include CustomFieldsHelper
# prevents login action to be filtered by check_if_login_required application scope filter
skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register]
before_filter :require_login, :only => :logout
# Show user's account
def show
@user = User.find(params[:id])
@custom_values = @user.custom_values.find(:all, :include => :custom_field)
rescue ActiveRecord::RecordNotFound
render_404
end
# Login request and validation
def login
if request.get?
# Logout user
self.logged_in_user = nil
else
# Authenticate user
user = User.try_to_login(params[:login], params[:password])
if user
self.logged_in_user = user
redirect_back_or_default :controller => 'my', :action => 'page'
else
flash.now[:notice] = l(:notice_account_invalid_creditentials)
end
end
end
# Log out current user and redirect to welcome page
def logout
self.logged_in_user = nil
redirect_to :controller => 'welcome'
end
# Enable user to choose a new password
def lost_password
redirect_to :controller => 'welcome' and return unless Setting.lost_password?
if params[:token]
@token = Token.find_by_action_and_value("recovery", params[:token])
redirect_to :controller => 'welcome' and return unless @token and !@token.expired?
@user = @token.user
if request.post?
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if @user.save
@token.destroy
flash[:notice] = l(:notice_account_password_updated)
redirect_to :action => 'login'
return
end
end
render :template => "account/password_recovery"
return
else
if request.post?
user = User.find_by_mail(params[:mail])
# user not found in db
flash.now[:notice] = l(:notice_account_unknown_email) and return unless user
# user uses an external authentification
flash.now[:notice] = l(:notice_can_t_change_password) and return if user.auth_source_id
# create a new token for password recovery
token = Token.new(:user => user, :action => "recovery")
if token.save
Mailer.deliver_lost_password(token)
flash[:notice] = l(:notice_account_lost_email_sent)
redirect_to :action => 'login'
return
end
end
end
end
# User self-registration
def register
redirect_to :controller => 'welcome' and return unless Setting.self_registration?
if params[:token]
token = Token.find_by_action_and_value("register", params[:token])
redirect_to :controller => 'welcome' and return unless token and !token.expired?
user = token.user
redirect_to :controller => 'welcome' and return unless user.status == User::STATUS_REGISTERED
user.status = User::STATUS_ACTIVE
if user.save
token.destroy
flash[:notice] = l(:notice_account_activated)
redirect_to :action => 'login'
return
end
else
if request.get?
@user = User.new(:language => Setting.default_language)
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
else
@user = User.new(params[:user])
@user.admin = false
@user.login = params[:user][:login]
@user.status = User::STATUS_REGISTERED
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values
token = Token.new(:user => @user, :action => "register")
if @user.save and token.save
Mailer.deliver_register(token)
flash[:notice] = l(:notice_account_register_done)
redirect_to :controller => 'welcome' and return
end
end
end
end
end

View File

@@ -1,54 +1,60 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AdminController < ApplicationController
layout 'base'
before_filter :require_admin
helper :sort
include SortHelper
def index
end
def projects
sort_init 'name', 'asc'
sort_update
@project_count = Project.count
@project_pages = Paginator.new self, @project_count,
15,
@params['page']
@projects = Project.find :all, :order => sort_clause,
:limit => @project_pages.items_per_page,
:offset => @project_pages.current.offset
end
def mail_options
@actions = Permission.find(:all, :conditions => ["mail_option=?", true]) || []
if request.post?
@actions.each { |a|
a.mail_enabled = (params[:action_ids] || []).include? a.id.to_s
a.save
}
flash.now[:notice] = l(:notice_successful_update)
end
end
def info
@adapter_name = ActiveRecord::Base.connection.adapter_name
end
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AdminController < ApplicationController
layout 'base'
before_filter :require_admin
helper :sort
include SortHelper
def index
end
def projects
sort_init 'name', 'asc'
sort_update
@project_count = Project.count
@project_pages = Paginator.new self, @project_count,
15,
params['page']
@projects = Project.find :all, :order => sort_clause,
:limit => @project_pages.items_per_page,
:offset => @project_pages.current.offset
render :action => "projects", :layout => false if request.xhr?
end
def mail_options
@actions = Permission.find(:all, :conditions => ["mail_option=?", true]) || []
if request.post?
@actions.each { |a|
a.mail_enabled = (params[:action_ids] || []).include? a.id.to_s
a.save
}
flash.now[:notice] = l(:notice_successful_update)
end
end
def info
@db_adapter_name = ActiveRecord::Base.connection.adapter_name
@flags = Hash.new
@flags[:default_admin_changed] = User.find(:first, :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?
@flags[:file_repository_writable] = File.writable?(Attachment.storage_path)
@flags[:textile_available] = ActionView::Helpers::TextHelper.method_defined? "textilize"
end
end

View File

@@ -1,107 +1,148 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ApplicationController < ActionController::Base
before_filter :check_if_login_required, :set_localization
def logged_in_user=(user)
@logged_in_user = user
session[:user_id] = (user ? user.id : nil)
end
def logged_in_user
if session[:user_id]
@logged_in_user ||= User.find(session[:user_id], :include => :memberships)
else
nil
end
end
# check if login is globally required to access the application
def check_if_login_required
require_login if $RDM_LOGIN_REQUIRED
end
def set_localization
lang = begin
if self.logged_in_user and self.logged_in_user.language and !self.logged_in_user.language.empty? and GLoc.valid_languages.include? self.logged_in_user.language.to_sym
self.logged_in_user.language
elsif request.env['HTTP_ACCEPT_LANGUAGE']
accept_lang = HTTPUtils.parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first
if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym
accept_lang
end
end
rescue
nil
end || $RDM_DEFAULT_LANG
set_language_if_valid(lang)
end
def require_login
unless self.logged_in_user
store_location
redirect_to :controller => "account", :action => "login"
return false
end
true
end
def require_admin
return unless require_login
unless self.logged_in_user.admin?
render :nothing => true, :status => 403
return false
end
true
end
# authorizes the user for the requested action.
def authorize
# check if action is allowed on public projects
if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ @params[:controller], @params[:action] ]
return true
end
# if action is not public, force login
return unless require_login
# admin is always authorized
return true if self.logged_in_user.admin?
# if not admin, check membership permission
@user_membership ||= Member.find(:first, :conditions => ["user_id=? and project_id=?", self.logged_in_user.id, @project.id])
if @user_membership and Permission.allowed_to_role( "%s/%s" % [ @params[:controller], @params[:action] ], @user_membership.role_id )
return true
end
render :nothing => true, :status => 403
false
end
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ApplicationController < ActionController::Base
before_filter :check_if_login_required, :set_localization
filter_parameter_logging :password
def logged_in_user=(user)
@logged_in_user = user
session[:user_id] = (user ? user.id : nil)
end
def logged_in_user
if session[:user_id]
@logged_in_user ||= User.find(session[:user_id])
else
nil
end
end
# Returns the role that the logged in user has on the current project
# or nil if current user is not a member of the project
def logged_in_user_membership
@user_membership ||= logged_in_user.role_for_project(@project)
end
# check if login is globally required to access the application
def check_if_login_required
require_login if Setting.login_required?
end
def set_localization
lang = begin
if self.logged_in_user and self.logged_in_user.language and !self.logged_in_user.language.empty? and GLoc.valid_languages.include? self.logged_in_user.language.to_sym
self.logged_in_user.language
elsif request.env['HTTP_ACCEPT_LANGUAGE']
accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first
if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym
accept_lang
end
end
rescue
nil
end || Setting.default_language
set_language_if_valid(lang)
end
def require_login
unless self.logged_in_user
store_location
redirect_to :controller => "account", :action => "login"
return false
end
true
end
def require_admin
return unless require_login
unless self.logged_in_user.admin?
render :nothing => true, :status => 403
return false
end
true
end
# authorizes the user for the requested action.
def authorize(ctrl = params[:controller], action = params[:action])
# check if action is allowed on public projects
if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ ctrl, action ]
return true
end
# if action is not public, force login
return unless require_login
# admin is always authorized
return true if self.logged_in_user.admin?
# if not admin, check membership permission
if logged_in_user_membership and Permission.allowed_to_role( "%s/%s" % [ ctrl, action ], logged_in_user_membership )
return true
end
render :nothing => true, :status => 403
false
end
# make sure that the user is a member of the project (or admin) if project is private
# used as a before_filter for actions that do not require any particular permission on the project
def check_project_privacy
return true if @project.is_public?
return false unless logged_in_user
return true if logged_in_user.admin? || logged_in_user_membership
render :nothing => true, :status => 403
false
end
# store current uri in session.
# return to this location by calling redirect_back_or_default
def store_location
session[:return_to] = @request.request_uri
session[:return_to_params] = params
end
# move to the last store_location call or to the passed default one
def redirect_back_or_default(default)
if session[:return_to].nil?
if session[:return_to_params].nil?
redirect_to default
else
redirect_to_url session[:return_to]
session[:return_to] = nil
redirect_to session[:return_to_params]
session[:return_to_params] = nil
end
end
def render_404
@html_title = "404"
render :template => "common/404", :layout => true, :status => 404
return false
end
# qvalues http header parser
# code taken from webrick
def parse_qvalues(value)
tmp = []
if value
parts = value.split(/,\s*/)
parts.each {|part|
if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
val = m[1]
q = (m[2] or 1).to_f
tmp.push([val, q])
end
}
tmp = tmp.sort_by{|val, q| -q}
tmp.collect!{|val, q| val}
end
return tmp
end
end

View File

@@ -21,7 +21,7 @@ class AuthSourcesController < ApplicationController
def index
list
render :action => 'list'
render :action => 'list' unless request.xhr?
end
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
@@ -30,6 +30,7 @@ class AuthSourcesController < ApplicationController
def list
@auth_source_pages, @auth_sources = paginate :auth_sources, :per_page => 10
render :action => "list", :layout => false if request.xhr?
end
def new

View File

@@ -1,70 +1,72 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomFieldsController < ApplicationController
layout 'base'
before_filter :require_admin
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomFieldsController < ApplicationController
layout 'base'
before_filter :require_admin
def index
list
render :action => 'list'
render :action => 'list' unless request.xhr?
end
def list
@custom_field_pages, @custom_fields = paginate :custom_fields, :per_page => 15
@custom_fields_by_type = CustomField.find(:all).group_by {|f| f.type.to_s }
@tab = params[:tab] || 'IssueCustomField'
render :action => "list", :layout => false if request.xhr?
end
def new
case params[:type]
when "IssueCustomField"
@custom_field = IssueCustomField.new(params[:custom_field])
@custom_field.trackers = Tracker.find(params[:tracker_ids]) if params[:tracker_ids]
when "UserCustomField"
@custom_field = UserCustomField.new(params[:custom_field])
when "ProjectCustomField"
@custom_field = ProjectCustomField.new(params[:custom_field])
else
redirect_to :action => 'list'
return
end
if request.post? and @custom_field.save
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list', :tab => @custom_field.type
end
@trackers = Tracker.find(:all, :order => 'position')
end
def edit
@custom_field = CustomField.find(params[:id])
if request.post? and @custom_field.update_attributes(params[:custom_field])
if @custom_field.is_a? IssueCustomField
@custom_field.trackers = params[:tracker_ids] ? Tracker.find(params[:tracker_ids]) : []
end
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'list', :tab => @custom_field.type
end
@trackers = Tracker.find(:all, :order => 'position')
end
def new
case params[:type]
when "IssueCustomField"
@custom_field = IssueCustomField.new(params[:custom_field])
@custom_field.trackers = Tracker.find(params[:tracker_ids]) if params[:tracker_ids]
when "UserCustomField"
@custom_field = UserCustomField.new(params[:custom_field])
when "ProjectCustomField"
@custom_field = ProjectCustomField.new(params[:custom_field])
else
redirect_to :action => 'list'
return
end
if request.post? and @custom_field.save
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list'
end
@trackers = Tracker.find(:all)
end
def edit
@custom_field = CustomField.find(params[:id])
if request.post? and @custom_field.update_attributes(params[:custom_field])
if @custom_field.is_a? IssueCustomField
@custom_field.trackers = params[:tracker_ids] ? Tracker.find(params[:tracker_ids]) : []
end
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'list'
end
@trackers = Tracker.find(:all)
end
def destroy
CustomField.find(params[:id]).destroy
redirect_to :action => 'list'
rescue
flash[:notice] = "Unable to delete custom field"
@custom_field = CustomField.find(params[:id]).destroy
redirect_to :action => 'list', :tab => @custom_field.type
rescue
flash[:notice] = "Unable to delete custom field"
redirect_to :action => 'list'
end
end
end

View File

@@ -1,65 +1,71 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class DocumentsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
def show
class DocumentsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
def show
@attachments = @document.attachments.find(:all, :order => "created_on DESC")
end
def edit
def edit
@categories = Enumeration::get_values('DCAT')
if request.post? and @document.update_attributes(params[:document])
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'show', :id => @document
end
end
end
def destroy
@document.destroy
redirect_to :controller => 'projects', :action => 'list_documents', :id => @project
end
def download
@attachment = @document.attachments.find(params[:attachment_id])
@attachment.increment_download
send_file @attachment.diskfile, :filename => @attachment.filename
end
def add_attachment
# Save the attachment
if params[:attachment][:file].size > 0
@attachment = @document.attachments.build(params[:attachment])
@attachment.author_id = self.logged_in_user.id if self.logged_in_user
@attachment.save
end
redirect_to :action => 'show', :id => @document
end
def destroy_attachment
@document.attachments.find(params[:attachment_id]).destroy
redirect_to :action => 'show', :id => @document
end
private
def find_project
@document = Document.find(params[:id])
@project = @document.project
def download
@attachment = @document.attachments.find(params[:attachment_id])
@attachment.increment_download
send_file @attachment.diskfile, :filename => @attachment.filename
rescue
render_404
end
def add_attachment
# Save the attachments
@attachments = []
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @document, :file => file, :author => logged_in_user)
@attachments << a unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'show', :id => @document
end
def destroy_attachment
@document.attachments.find(params[:attachment_id]).destroy
redirect_to :action => 'show', :id => @document
end
private
def find_project
@document = Document.find(params[:id])
@project = @document.project
rescue ActiveRecord::RecordNotFound
render_404
end
end

View File

@@ -1,23 +1,23 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class EnumerationsController < ApplicationController
layout 'base'
before_filter :require_admin
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class EnumerationsController < ApplicationController
layout 'base'
before_filter :require_admin
def index
list
@@ -60,11 +60,11 @@ class EnumerationsController < ApplicationController
end
def destroy
Enumeration.find(params[:id]).destroy
Enumeration.find(params[:id]).destroy
flash[:notice] = l(:notice_successful_delete)
redirect_to :action => 'list'
rescue
flash[:notice] = "Unable to delete enumeration"
redirect_to :action => 'list'
rescue
flash[:notice] = "Unable to delete enumeration"
redirect_to :action => 'list'
end
end

View File

@@ -0,0 +1,96 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class FeedsController < ApplicationController
before_filter :find_scope
session :off
helper :issues
include IssuesHelper
helper :custom_fields
include CustomFieldsHelper
# news feeds
def news
News.with_scope(:find => @find_options) do
@news = News.find :all, :order => "#{News.table_name}.created_on DESC", :include => [ :author, :project ]
end
headers["Content-Type"] = "application/rss+xml"
render :action => 'news_atom' if 'atom' == params[:format]
end
# issue feeds
def issues
if @project && params[:query_id]
query = Query.find(params[:query_id])
# ignore query if it's not valid
query = nil unless query.valid?
# override with query conditions
@find_options[:conditions] = query.statement if query.valid? and @project == query.project
end
Issue.with_scope(:find => @find_options) do
@issues = Issue.find :all, :include => [:project, :author, :tracker, :status],
:order => "#{Issue.table_name}.created_on DESC"
end
@title = (@project ? @project.name : Setting.app_title) + ": " + (query ? query.name : l(:label_reported_issues))
headers["Content-Type"] = "application/rss+xml"
render :action => 'issues_atom' if 'atom' == params[:format]
end
# issue changes feeds
def history
if @project && params[:query_id]
query = Query.find(params[:query_id])
# ignore query if it's not valid
query = nil unless query.valid?
# override with query conditions
@find_options[:conditions] = query.statement if query.valid? and @project == query.project
end
Journal.with_scope(:find => @find_options) do
@journals = Journal.find :all, :include => [ :details, :user, {:issue => [:project, :author, :tracker, :status]} ],
:order => "#{Journal.table_name}.created_on DESC"
end
@title = (@project ? @project.name : Setting.app_title) + ": " + (query ? query.name : l(:label_reported_issues))
headers["Content-Type"] = "application/rss+xml"
render :action => 'history_atom' if 'atom' == params[:format]
end
private
# override for feeds specific authentication
def check_if_login_required
@user = User.find_by_rss_key(params[:key])
render(:nothing => true, :status => 403) and return false if !@user && Setting.login_required?
end
def find_scope
if params[:project_id]
# project feed
# check if project is public or if the user is a member
@project = Project.find(params[:project_id])
render(:nothing => true, :status => 403) and return false unless @project.is_public? || (@user && @user.role_for_project(@project))
scope = ["#{Project.table_name}.id=?", params[:project_id].to_i]
else
# global feed
scope = ["#{Project.table_name}.is_public=?", true]
end
@find_options = {:conditions => scope, :limit => Setting.feeds_limit}
return true
end
end

View File

@@ -1,47 +1,44 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class HelpController < ApplicationController
skip_before_filter :check_if_login_required
before_filter :load_help_config
# displays help page for the requested controller/action
def index
# select help page to display
if @params[:ctrl] and @help_config['pages'][@params[:ctrl]]
if @params[:page] and @help_config['pages'][@params[:ctrl]][@params[:page]]
template = @help_config['pages'][@params[:ctrl]][@params[:page]]
else
template = @help_config['pages'][@params[:ctrl]]['index']
end
end
# choose language according to available help translations
lang = (@help_config['langs'].include? current_language) ? current_language : @help_config['langs'].first
if template
redirect_to "/manual/#{lang}/#{template}"
else
redirect_to "/manual/#{lang}/"
end
end
private
def load_help_config
@help_config = YAML::load(File.open("#{RAILS_ROOT}/config/help.yml"))
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class HelpController < ApplicationController
skip_before_filter :check_if_login_required
before_filter :load_help_config
# displays help page for the requested controller/action
def index
# select help page to display
if params[:ctrl] and @help_config['pages'][params[:ctrl]]
if params[:page] and @help_config['pages'][params[:ctrl]][params[:page]]
template = @help_config['pages'][params[:ctrl]][params[:page]]
else
template = @help_config['pages'][params[:ctrl]]['index']
end
end
# choose language according to available help translations
lang = (@help_config['langs'].include? current_language.to_s) ? current_language.to_s : @help_config['langs'].first
url = "/manual/#{lang}/" + (template || "index.html")
redirect_to(request.relative_url_root + url)
end
private
def load_help_config
@help_config = YAML::load(File.open("#{RAILS_ROOT}/config/help.yml"))
end
end

View File

@@ -1,42 +1,44 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCategoriesController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
layout 'base'
before_filter :find_project, :authorize
def edit
if request.post? and @category.update_attributes(params[:category])
flash[:notice] = l(:notice_successful_update)
redirect_to :controller => 'projects', :action => 'settings', :id => @project
redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project
end
end
def destroy
@category.destroy
redirect_to :controller => 'projects', :action => 'settings', :id => @project
rescue
redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project
rescue
flash[:notice] = "Categorie can't be deleted"
redirect_to :controller => 'projects', :action => 'settings', :id => @project
end
redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project
end
private
def find_project
@category = IssueCategory.find(params[:id])
@project = @category.project
end
private
def find_project
@category = IssueCategory.find(params[:id])
@project = @category.project
rescue ActiveRecord::RecordNotFound
render_404
end
end

View File

@@ -1,31 +1,35 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueStatusesController < ApplicationController
layout 'base'
before_filter :require_admin
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueStatusesController < ApplicationController
layout 'base'
before_filter :require_admin
verify :method => :post, :only => [ :destroy, :create, :update, :move ],
:redirect_to => { :action => :list }
def index
list
render :action => 'list'
render :action => 'list' unless request.xhr?
end
def list
@issue_status_pages, @issue_statuses = paginate :issue_statuses, :per_page => 10
@issue_status_pages, @issue_statuses = paginate :issue_statuses, :per_page => 25, :order => "position"
render :action => "list", :layout => false if request.xhr?
end
def new
@@ -55,14 +59,27 @@ class IssueStatusesController < ApplicationController
render :action => 'edit'
end
end
def move
@issue_status = IssueStatus.find(params[:id])
case params[:position]
when 'highest'
@issue_status.move_to_top
when 'higher'
@issue_status.move_higher
when 'lower'
@issue_status.move_lower
when 'lowest'
@issue_status.move_to_bottom
end if params[:position]
redirect_to :action => 'list'
end
def destroy
IssueStatus.find(params[:id]).destroy
redirect_to :action => 'list'
rescue
flash[:notice] = "Unable to delete issue status"
redirect_to :action => 'list'
end
rescue
flash[:notice] = "Unable to delete issue status"
redirect_to :action => 'list'
end
end

View File

@@ -0,0 +1,159 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssuesController < ApplicationController
layout 'base', :except => :export_pdf
before_filter :find_project, :authorize
helper :custom_fields
include CustomFieldsHelper
helper :ifpdf
include IfpdfHelper
def show
@status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
@custom_values = @issue.custom_values.find(:all, :include => :custom_field)
@journals_count = @issue.journals.count
@journals = @issue.journals.find(:all, :include => [:user, :details], :limit => 15, :order => "#{Journal.table_name}.created_on desc")
end
def history
@journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on desc")
@journals_count = @journals.length
end
def export_pdf
@custom_values = @issue.custom_values.find(:all, :include => :custom_field)
@options_for_rfpdf ||= {}
@options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.long_id}.pdf"
end
def edit
@priorities = Enumeration::get_values('IPRI')
if request.get?
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
else
begin
@issue.init_journal(self.logged_in_user)
# Retrieve custom fields and values
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
@issue.custom_values = @custom_values
@issue.attributes = params[:issue]
if @issue.save
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'show', :id => @issue
end
rescue ActiveRecord::StaleObjectError
# Optimistic locking exception
flash[:notice] = l(:notice_locking_conflict)
end
end
end
def add_note
unless params[:notes].empty?
journal = @issue.init_journal(self.logged_in_user, params[:notes])
if @issue.save
flash[:notice] = l(:notice_successful_update)
Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'show', :id => @issue
return
end
end
show
render :action => 'show'
end
def change_status
@status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
@new_status = IssueStatus.find(params[:new_status_id])
if params[:confirm]
begin
journal = @issue.init_journal(self.logged_in_user, params[:notes])
@issue.status = @new_status
if @issue.update_attributes(params[:issue])
# Save attachments
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => a.id,
:value => a.filename) unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
flash[:notice] = l(:notice_successful_update)
Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'show', :id => @issue
end
rescue ActiveRecord::StaleObjectError
# Optimistic locking exception
flash[:notice] = l(:notice_locking_conflict)
end
end
@assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
end
def destroy
@issue.destroy
redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
end
def add_attachment
# Save the attachments
@attachments = []
journal = @issue.init_journal(self.logged_in_user)
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
@attachments << a unless a.new_record?
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => a.id,
:value => a.filename) unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
journal.save if journal.details.any?
Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'show', :id => @issue
end
def destroy_attachment
a = @issue.attachments.find(params[:attachment_id])
a.destroy
journal = @issue.init_journal(self.logged_in_user)
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => a.id,
:old_value => a.filename)
journal.save
redirect_to :action => 'show', :id => @issue
end
# Send the file in stream mode
def download
@attachment = @issue.attachments.find(params[:attachment_id])
send_file @attachment.diskfile, :filename => @attachment.filename
rescue
render_404
end
private
def find_project
@issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
@project = @issue.project
@html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
rescue ActiveRecord::RecordNotFound
render_404
end
end

View File

@@ -1,41 +1,42 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MembersController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
layout 'base'
before_filter :find_project, :authorize
def edit
if request.post? and @member.update_attributes(params[:member])
flash[:notice] = l(:notice_successful_update)
redirect_to :controller => 'projects', :action => 'settings', :id => @project
end
end
def edit
if request.post? and @member.update_attributes(params[:member])
flash[:notice] = l(:notice_successful_update)
redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project
end
end
def destroy
@member.destroy
def destroy
@member.destroy
flash[:notice] = l(:notice_successful_delete)
redirect_to :controller => 'projects', :action => 'settings', :id => @project
end
private
def find_project
@member = Member.find(params[:id])
@project = @member.project
end
redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project
end
private
def find_project
@member = Member.find(params[:id])
@project = @member.project
rescue ActiveRecord::RecordNotFound
render_404
end
end

View File

@@ -0,0 +1,136 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MyController < ApplicationController
layout 'base'
before_filter :require_login
BLOCKS = { 'issuesassignedtome' => :label_assigned_to_me_issues,
'issuesreportedbyme' => :label_reported_issues,
'news' => :label_news_latest,
'calendar' => :label_calendar,
'documents' => :label_document_plural
}.freeze
DEFAULT_LAYOUT = { 'left' => ['issuesassignedtome'],
'right' => ['issuesreportedbyme']
}.freeze
verify :xhr => true,
:session => :page_layout,
:only => [:add_block, :remove_block, :order_blocks]
def index
page
render :action => 'page'
end
# Show user's page
def page
@user = self.logged_in_user
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT
end
# Edit user's account
def account
@user = self.logged_in_user
@pref = @user.pref
@user.attributes = params[:user]
@user.pref.attributes = params[:pref]
if request.post? and @user.save and @user.pref.save
set_localization
flash.now[:notice] = l(:notice_account_updated)
self.logged_in_user.reload
end
end
# Change user's password
def change_password
@user = self.logged_in_user
flash[:notice] = l(:notice_can_t_change_password) and redirect_to :action => 'account' and return if @user.auth_source_id
if @user.check_password?(params[:password])
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if @user.save
flash[:notice] = l(:notice_account_password_updated)
else
render :action => 'account'
return
end
else
flash[:notice] = l(:notice_account_wrong_password)
end
redirect_to :action => 'account'
end
# User's page layout configuration
def page_layout
@user = self.logged_in_user
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT.dup
session[:page_layout] = @blocks
%w(top left right).each {|f| session[:page_layout][f] ||= [] }
@block_options = []
BLOCKS.each {|k, v| @block_options << [l(v), k]}
end
# Add a block to user's page
# The block is added on top of the page
# params[:block] : id of the block to add
def add_block
block = params[:block]
render(:nothing => true) and return unless block && (BLOCKS.keys.include? block)
@user = self.logged_in_user
# remove if already present in a group
%w(top left right).each {|f| (session[:page_layout][f] ||= []).delete block }
# add it on top
session[:page_layout]['top'].unshift block
render :partial => "block", :locals => {:user => @user, :block_name => block}
end
# Remove a block to user's page
# params[:block] : id of the block to remove
def remove_block
block = params[:block]
# remove block in all groups
%w(top left right).each {|f| (session[:page_layout][f] ||= []).delete block }
render :nothing => true
end
# Change blocks order on user's page
# params[:group] : group to order (top, left or right)
# params[:list-(top|left|right)] : array of block ids of the group
def order_blocks
group = params[:group]
group_items = params["list-#{group}"]
if group_items and group_items.is_a? Array
# remove group blocks if they are presents in other groups
%w(top left right).each {|f|
session[:page_layout][f] = (session[:page_layout][f] || []) - group_items
}
session[:page_layout][group] = group_items
end
render :nothing => true
end
# Save user's page layout
def page_layout_save
@user = self.logged_in_user
@user.pref[:my_page_layout] = session[:page_layout] if session[:page_layout]
@user.pref.save
session[:page_layout] = nil
redirect_to :action => 'page'
end
end

View File

@@ -1,23 +1,23 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class NewsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class NewsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
def show
end
@@ -28,15 +28,33 @@ class NewsController < ApplicationController
redirect_to :action => 'show', :id => @news
end
end
def add_comment
@comment = Comment.new(params[:comment])
@comment.author = logged_in_user
if @news.comments << @comment
flash[:notice] = l(:label_comment_added)
redirect_to :action => 'show', :id => @news
else
render :action => 'show'
end
end
def destroy
@news.destroy
redirect_to :controller => 'projects', :action => 'list_news', :id => @project
end
private
def find_project
@news = News.find(params[:id])
@project = @news.project
end
def destroy_comment
@news.comments.find(params[:comment_id]).destroy
redirect_to :action => 'show', :id => @news
end
def destroy
@news.destroy
redirect_to :controller => 'projects', :action => 'list_news', :id => @project
end
private
def find_project
@news = News.find(params[:id])
@project = @news.project
rescue ActiveRecord::RecordNotFound
render_404
end
end

View File

@@ -0,0 +1,691 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'csv'
class ProjectsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize, :except => [ :index, :list, :add ]
before_filter :require_admin, :only => [ :add, :destroy ]
helper :sort
include SortHelper
helper :custom_fields
include CustomFieldsHelper
helper :ifpdf
include IfpdfHelper
helper IssuesHelper
helper :queries
include QueriesHelper
def index
list
render :action => 'list' unless request.xhr?
end
# Lists public projects
def list
sort_init "#{Project.table_name}.name", "asc"
sort_update
@project_count = Project.count(:all, :conditions => ["is_public=?", true])
@project_pages = Paginator.new self, @project_count,
15,
params['page']
@projects = Project.find :all, :order => sort_clause,
:conditions => ["#{Project.table_name}.is_public=?", true],
:include => :parent,
:limit => @project_pages.items_per_page,
:offset => @project_pages.current.offset
render :action => "list", :layout => false if request.xhr?
end
# Add a new project
def add
@custom_fields = IssueCustomField.find(:all)
@root_projects = Project.find(:all, :conditions => "parent_id is null")
@project = Project.new(params[:project])
if request.get?
@custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
else
@project.custom_fields = CustomField.find(params[:custom_field_ids]) if params[:custom_field_ids]
@custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
@project.custom_values = @custom_values
if params[:repository_enabled] && params[:repository_enabled] == "1"
@project.repository = Repository.new
@project.repository.attributes = params[:repository]
end
if "1" == params[:wiki_enabled]
@project.wiki = Wiki.new
@project.wiki.attributes = params[:wiki]
end
if @project.save
flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'admin', :action => 'projects'
end
end
end
# Show @project
def show
@custom_values = @project.custom_values.find(:all, :include => :custom_field)
@members_by_role = @project.members.find(:all, :include => [:user, :role], :order => 'position').group_by {|m| m.role}
@subprojects = @project.children if @project.children.size > 0
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
@trackers = Tracker.find(:all, :order => 'position')
@open_issues_by_tracker = Issue.count(:group => :tracker, :joins => "INNER JOIN #{IssueStatus.table_name} ON #{IssueStatus.table_name}.id = #{Issue.table_name}.status_id", :conditions => ["project_id=? and #{IssueStatus.table_name}.is_closed=?", @project.id, false])
@total_issues_by_tracker = Issue.count(:group => :tracker, :conditions => ["project_id=?", @project.id])
end
def settings
@root_projects = Project::find(:all, :conditions => ["parent_id is null and id <> ?", @project.id])
@custom_fields = IssueCustomField.find(:all)
@issue_category ||= IssueCategory.new
@member ||= @project.members.new
@roles = Role.find(:all, :order => 'position')
@users = User.find_active(:all) - @project.users
@custom_values ||= ProjectCustomField.find(:all).collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
end
# Edit @project
def edit
if request.post?
@project.custom_fields = IssueCustomField.find(params[:custom_field_ids]) if params[:custom_field_ids]
if params[:custom_fields]
@custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
@project.custom_values = @custom_values
end
if params[:repository_enabled]
case params[:repository_enabled]
when "0"
@project.repository = nil
when "1"
@project.repository ||= Repository.new
@project.repository.update_attributes params[:repository]
end
end
if params[:wiki_enabled]
case params[:wiki_enabled]
when "0"
@project.wiki.destroy if @project.wiki
when "1"
@project.wiki ||= Wiki.new
@project.wiki.update_attributes params[:wiki]
end
end
@project.attributes = params[:project]
if @project.save
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'settings', :id => @project
else
settings
render :action => 'settings'
end
end
end
# Delete @project
def destroy
if request.post? and params[:confirm]
@project.destroy
redirect_to :controller => 'admin', :action => 'projects'
end
end
# Add a new issue category to @project
def add_issue_category
if request.post?
@issue_category = @project.issue_categories.build(params[:issue_category])
if @issue_category.save
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'settings', :tab => 'categories', :id => @project
else
settings
render :action => 'settings'
end
end
end
# Add a new version to @project
def add_version
@version = @project.versions.build(params[:version])
if request.post? and @version.save
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'settings', :tab => 'versions', :id => @project
end
end
# Add a new member to @project
def add_member
@member = @project.members.build(params[:member])
if request.post?
if @member.save
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'settings', :tab => 'members', :id => @project
else
settings
render :action => 'settings'
end
end
end
# Show members list of @project
def list_members
@members = @project.members.find(:all)
end
# Add a new document to @project
def add_document
@categories = Enumeration::get_values('DCAT')
@document = @project.documents.build(params[:document])
if request.post? and @document.save
# Save the attachments
params[:attachments].each { |a|
Attachment.create(:container => @document, :file => a, :author => logged_in_user) unless a.size == 0
} if params[:attachments] and params[:attachments].is_a? Array
flash[:notice] = l(:notice_successful_create)
Mailer.deliver_document_add(@document) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'list_documents', :id => @project
end
end
# Show documents list of @project
def list_documents
@documents = @project.documents.find :all, :include => :category
end
# Add a new issue to @project
def add_issue
@tracker = Tracker.find(params[:tracker_id])
@priorities = Enumeration::get_values('IPRI')
default_status = IssueStatus.default
@issue = Issue.new(:project => @project, :tracker => @tracker)
@issue.status = default_status
@allowed_statuses = default_status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
if request.get?
@issue.start_date = Date.today
@custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) }
else
@issue.attributes = params[:issue]
requested_status = IssueStatus.find_by_id(params[:issue][:status_id])
@issue.status = (@allowed_statuses.include? requested_status) ? requested_status : default_status
@issue.author_id = self.logged_in_user.id if self.logged_in_user
# Multiple file upload
@attachments = []
params[:attachments].each { |a|
@attachments << Attachment.new(:container => @issue, :file => a, :author => logged_in_user) unless a.size == 0
} if params[:attachments] and params[:attachments].is_a? Array
@custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
@issue.custom_values = @custom_values
if @issue.save
@attachments.each(&:save)
flash[:notice] = l(:notice_successful_create)
Mailer.deliver_issue_add(@issue) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'list_issues', :id => @project
end
end
end
# Show filtered/sorted issues list of @project
def list_issues
sort_init "#{Issue.table_name}.id", "desc"
sort_update
retrieve_query
@results_per_page_options = [ 15, 25, 50, 100 ]
if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
@results_per_page = params[:per_page].to_i
session[:results_per_page] = @results_per_page
else
@results_per_page = session[:results_per_page] || 25
end
if @query.valid?
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
@issue_pages = Paginator.new self, @issue_count, @results_per_page, params['page']
@issues = Issue.find :all, :order => sort_clause,
:include => [ :assigned_to, :status, :tracker, :project, :priority ],
:conditions => @query.statement,
:limit => @issue_pages.items_per_page,
:offset => @issue_pages.current.offset
end
@trackers = Tracker.find :all, :order => 'position'
render :layout => false if request.xhr?
end
# Export filtered/sorted issues list to CSV
def export_issues_csv
sort_init "#{Issue.table_name}.id", "desc"
sort_update
retrieve_query
render :action => 'list_issues' and return unless @query.valid?
@issues = Issue.find :all, :order => sort_clause,
:include => [ :assigned_to, :author, :status, :tracker, :priority, {:custom_values => :custom_field} ],
:conditions => @query.statement,
:limit => Setting.issues_export_limit
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
export = StringIO.new
CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
# csv header fields
headers = [ "#", l(:field_status),
l(:field_tracker),
l(:field_priority),
l(:field_subject),
l(:field_assigned_to),
l(:field_author),
l(:field_start_date),
l(:field_due_date),
l(:field_done_ratio),
l(:field_created_on),
l(:field_updated_on)
]
for custom_field in @project.all_custom_fields
headers << custom_field.name
end
csv << headers.collect {|c| ic.iconv(c) }
# csv lines
@issues.each do |issue|
fields = [issue.id, issue.status.name,
issue.tracker.name,
issue.priority.name,
issue.subject,
(issue.assigned_to ? issue.assigned_to.name : ""),
issue.author.name,
issue.start_date ? l_date(issue.start_date) : nil,
issue.due_date ? l_date(issue.due_date) : nil,
issue.done_ratio,
l_datetime(issue.created_on),
l_datetime(issue.updated_on)
]
for custom_field in @project.all_custom_fields
fields << (show_value issue.custom_value_for(custom_field))
end
csv << fields.collect {|c| ic.iconv(c.to_s) }
end
end
export.rewind
send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
end
# Export filtered/sorted issues to PDF
def export_issues_pdf
sort_init "#{Issue.table_name}.id", "desc"
sort_update
retrieve_query
render :action => 'list_issues' and return unless @query.valid?
@issues = Issue.find :all, :order => sort_clause,
:include => [ :author, :status, :tracker, :priority ],
:conditions => @query.statement,
:limit => Setting.issues_export_limit
@options_for_rfpdf ||= {}
@options_for_rfpdf[:file_name] = "export.pdf"
render :layout => false
end
def move_issues
@issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids]
redirect_to :action => 'list_issues', :id => @project and return unless @issues
@projects = []
# find projects to which the user is allowed to move the issue
@logged_in_user.memberships.each {|m| @projects << m.project if Permission.allowed_to_role("projects/move_issues", m.role)}
# issue can be moved to any tracker
@trackers = Tracker.find(:all)
if request.post? and params[:new_project_id] and params[:new_tracker_id]
new_project = Project.find(params[:new_project_id])
new_tracker = Tracker.find(params[:new_tracker_id])
@issues.each { |i|
# project dependent properties
unless i.project_id == new_project.id
i.category = nil
i.fixed_version = nil
end
# move the issue
i.project = new_project
i.tracker = new_tracker
i.save
}
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'list_issues', :id => @project
end
end
def add_query
@query = Query.new(params[:query])
@query.project = @project
@query.user = logged_in_user
params[:fields].each do |field|
@query.add_filter(field, params[:operators][field], params[:values][field])
end if params[:fields]
if request.post? and @query.save
flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'reports', :action => 'issue_report', :id => @project
end
render :layout => false if request.xhr?
end
# Add a news to @project
def add_news
@news = News.new(:project => @project)
if request.post?
@news.attributes = params[:news]
@news.author_id = self.logged_in_user.id if self.logged_in_user
if @news.save
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list_news', :id => @project
end
end
end
# Show news list of @project
def list_news
@news_pages, @news = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "#{News.table_name}.created_on DESC"
render :action => "list_news", :layout => false if request.xhr?
end
def add_file
if request.post?
@version = @project.versions.find_by_id(params[:version_id])
# Save the attachments
@attachments = []
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @version, :file => file, :author => logged_in_user)
@attachments << a unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :controller => 'projects', :action => 'list_files', :id => @project
end
@versions = @project.versions
end
def list_files
@versions = @project.versions
end
# Show changelog for @project
def changelog
@trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true], :order => 'position')
retrieve_selected_tracker_ids(@trackers)
@fixed_issues = @project.issues.find(:all,
:include => [ :fixed_version, :status, :tracker ],
:conditions => [ "#{IssueStatus.table_name}.is_closed=? and #{Issue.table_name}.tracker_id in (#{@selected_tracker_ids.join(',')}) and #{Issue.table_name}.fixed_version_id is not null", true],
:order => "#{Version.table_name}.effective_date DESC, #{Issue.table_name}.id DESC"
) unless @selected_tracker_ids.empty?
@fixed_issues ||= []
end
def roadmap
@trackers = Tracker.find(:all, :conditions => ["is_in_roadmap=?", true], :order => 'position')
retrieve_selected_tracker_ids(@trackers)
@versions = @project.versions.find(:all,
:conditions => [ "#{Version.table_name}.effective_date>?", Date.today],
:order => "#{Version.table_name}.effective_date ASC"
)
end
def activity
if params[:year] and params[:year].to_i > 1900
@year = params[:year].to_i
if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
@month = params[:month].to_i
end
end
@year ||= Date.today.year
@month ||= Date.today.month
@date_from = Date.civil(@year, @month, 1)
@date_to = (@date_from >> 1)-1
@events_by_day = {}
unless params[:show_issues] == "0"
@project.issues.find(:all, :include => [:author], :conditions => ["#{Issue.table_name}.created_on>=? and #{Issue.table_name}.created_on<=?", @date_from, @date_to] ).each { |i|
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
@show_issues = 1
end
unless params[:show_news] == "0"
@project.news.find(:all, :conditions => ["#{News.table_name}.created_on>=? and #{News.table_name}.created_on<=?", @date_from, @date_to], :include => :author ).each { |i|
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
@show_news = 1
end
unless params[:show_files] == "0"
Attachment.find(:all, :select => "#{Attachment.table_name}.*", :joins => "LEFT JOIN #{Version.table_name} ON #{Version.table_name}.id = #{Attachment.table_name}.container_id", :conditions => ["#{Attachment.table_name}.container_type='Version' and #{Version.table_name}.project_id=? and #{Attachment.table_name}.created_on>=? and #{Attachment.table_name}.created_on<=?", @project.id, @date_from, @date_to], :include => :author ).each { |i|
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
@show_files = 1
end
unless params[:show_documents] == "0"
@project.documents.find(:all, :conditions => ["#{Document.table_name}.created_on>=? and #{Document.table_name}.created_on<=?", @date_from, @date_to] ).each { |i|
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
Attachment.find(:all, :select => "attachments.*", :joins => "LEFT JOIN #{Document.table_name} ON #{Document.table_name}.id = #{Attachment.table_name}.container_id", :conditions => ["#{Attachment.table_name}.container_type='Document' and #{Document.table_name}.project_id=? and #{Attachment.table_name}.created_on>=? and #{Attachment.table_name}.created_on<=?", @project.id, @date_from, @date_to], :include => :author ).each { |i|
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
@show_documents = 1
end
unless params[:show_wiki_edits] == "0"
select = "#{WikiContent.versioned_table_name}.updated_on, #{WikiContent.versioned_table_name}.comment, " +
"#{WikiContent.versioned_table_name}.#{WikiContent.version_column}, #{WikiPage.table_name}.title"
joins = "LEFT JOIN #{WikiPage.table_name} ON #{WikiPage.table_name}.id = #{WikiContent.versioned_table_name}.page_id " +
"LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id "
conditions = ["#{Wiki.table_name}.project_id = ? AND #{WikiContent.versioned_table_name}.updated_on BETWEEN ? AND ?",
@project.id, @date_from, @date_to]
WikiContent.versioned_class.find(:all, :select => select, :joins => joins, :conditions => conditions).each { |i|
# We provide this alias so all events can be treated in the same manner
def i.created_on
self.updated_on
end
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
@show_wiki_edits = 1
end
unless @project.repository.nil? || params[:show_changesets] == "0"
@project.repository.changesets.find(:all, :conditions => ["#{Changeset.table_name}.committed_on BETWEEN ? AND ?", @date_from, @date_to]).each { |i|
def i.created_on
self.committed_on
end
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
@show_changesets = 1
end
render :layout => false if request.xhr?
end
def calendar
@trackers = Tracker.find(:all, :order => 'position')
retrieve_selected_tracker_ids(@trackers)
if params[:year] and params[:year].to_i > 1900
@year = params[:year].to_i
if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
@month = params[:month].to_i
end
end
@year ||= Date.today.year
@month ||= Date.today.month
@date_from = Date.civil(@year, @month, 1)
@date_to = (@date_from >> 1)-1
# start on monday
@date_from = @date_from - (@date_from.cwday-1)
# finish on sunday
@date_to = @date_to + (7-@date_to.cwday)
@events = []
@project.issues_with_subprojects(params[:with_subprojects]) do
@events += Issue.find(:all,
:include => [:tracker, :status, :assigned_to, :priority],
:conditions => ["((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?)) and #{Issue.table_name}.tracker_id in (#{@selected_tracker_ids.join(',')})", @date_from, @date_to, @date_from, @date_to]
) unless @selected_tracker_ids.empty?
end
@events += @project.versions.find(:all, :conditions => ["effective_date BETWEEN ? AND ?", @date_from, @date_to])
@ending_events_by_days = @events.group_by {|event| event.due_date}
@starting_events_by_days = @events.group_by {|event| event.start_date}
render :layout => false if request.xhr?
end
def gantt
@trackers = Tracker.find(:all, :order => 'position')
retrieve_selected_tracker_ids(@trackers)
if params[:year] and params[:year].to_i >0
@year_from = params[:year].to_i
if params[:month] and params[:month].to_i >=1 and params[:month].to_i <= 12
@month_from = params[:month].to_i
else
@month_from = 1
end
else
@month_from ||= (Date.today << 1).month
@year_from ||= (Date.today << 1).year
end
@zoom = (params[:zoom].to_i > 0 and params[:zoom].to_i < 5) ? params[:zoom].to_i : 2
@months = (params[:months].to_i > 0 and params[:months].to_i < 25) ? params[:months].to_i : 6
@date_from = Date.civil(@year_from, @month_from, 1)
@date_to = (@date_from >> @months) - 1
@events = []
@project.issues_with_subprojects(params[:with_subprojects]) do
@events += Issue.find(:all,
:order => "start_date, due_date",
:include => [:tracker, :status, :assigned_to, :priority],
:conditions => ["(((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?) or (start_date<? and due_date>?)) and start_date is not null and due_date is not null and #{Issue.table_name}.tracker_id in (#{@selected_tracker_ids.join(',')}))", @date_from, @date_to, @date_from, @date_to, @date_from, @date_to]
) unless @selected_tracker_ids.empty?
end
@events += @project.versions.find(:all, :conditions => ["effective_date BETWEEN ? AND ?", @date_from, @date_to])
@events.sort! {|x,y| x.start_date <=> y.start_date }
if params[:output]=='pdf'
@options_for_rfpdf ||= {}
@options_for_rfpdf[:file_name] = "gantt.pdf"
render :template => "projects/gantt.rfpdf", :layout => false
else
render :template => "projects/gantt.rhtml"
end
end
def search
@question = params[:q] || ""
@question.strip!
@all_words = params[:all_words] || (params[:submit] ? false : true)
@scope = params[:scope] || (params[:submit] ? [] : %w(issues changesets news documents wiki) )
# tokens must be at least 3 character long
@tokens = @question.split.uniq.select {|w| w.length > 2 }
if !@tokens.empty?
# no more than 5 tokens to search for
@tokens.slice! 5..-1 if @tokens.size > 5
# strings used in sql like statement
like_tokens = @tokens.collect {|w| "%#{w}%"}
operator = @all_words ? " AND " : " OR "
limit = 10
@results = []
@results += @project.issues.find(:all, :limit => limit, :include => :author, :conditions => [ (["(LOWER(subject) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'issues'
@results += @project.news.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort], :include => :author ) if @scope.include? 'news'
@results += @project.documents.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'documents'
@results += @project.wiki.pages.find(:all, :limit => limit, :include => :content, :conditions => [ (["(LOWER(title) like ? OR LOWER(text) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @project.wiki && @scope.include?('wiki')
@results += @project.repository.changesets.find(:all, :limit => limit, :conditions => [ (["(LOWER(comment) like ?)"] * like_tokens.size).join(operator), * (like_tokens).sort] ) if @project.repository && @scope.include?('changesets')
@question = @tokens.join(" ")
else
@question = ""
end
end
def feeds
@queries = @project.queries.find :all, :conditions => ["is_public=? or user_id=?", true, (logged_in_user ? logged_in_user.id : 0)]
@key = logged_in_user.get_or_create_rss_key.value if logged_in_user
end
private
# Find project of id params[:id]
# if not found, redirect to project list
# Used as a before_filter
def find_project
@project = Project.find(params[:id])
@html_title = @project.name
rescue ActiveRecord::RecordNotFound
render_404
end
def retrieve_selected_tracker_ids(selectable_trackers)
if ids = params[:tracker_ids]
@selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
else
@selected_tracker_ids = selectable_trackers.collect {|t| t.id.to_s }
end
end
# Retrieve query from session or build a new query
def retrieve_query
if params[:query_id]
@query = @project.queries.find(params[:query_id])
session[:query] = @query
else
if params[:set_filter] or !session[:query] or session[:query].project_id != @project.id
# Give it a name, required to be valid
@query = Query.new(:name => "_")
@query.project = @project
if params[:fields] and params[:fields].is_a? Array
params[:fields].each do |field|
@query.add_filter(field, params[:operators][field], params[:values][field])
end
else
@query.available_filters.keys.each do |field|
@query.add_short_filter(field, params[field]) if params[field]
end
end
session[:query] = @query
else
@query = session[:query]
end
end
end
end

View File

@@ -0,0 +1,51 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class QueriesController < ApplicationController
layout 'base'
before_filter :require_login, :find_query
def edit
if request.post?
@query.filters = {}
params[:fields].each do |field|
@query.add_filter(field, params[:operators][field], params[:values][field])
end if params[:fields]
@query.attributes = params[:query]
if @query.save
flash[:notice] = l(:notice_successful_update)
redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
end
end
end
def destroy
@query.destroy if request.post?
redirect_to :controller => 'reports', :action => 'issue_report', :id => @project
end
private
def find_query
@query = Query.find(params[:id])
@project = @query.project
# check if user is allowed to manage queries (same permission as add_query)
authorize('projects', 'add_query')
rescue ActiveRecord::RecordNotFound
render_404
end
end

View File

@@ -0,0 +1,191 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ReportsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
def issue_report
@statuses = IssueStatus.find(:all, :order => 'position')
case params[:detail]
when "tracker"
@field = "tracker_id"
@rows = Tracker.find :all, :order => 'position'
@data = issues_by_tracker
@report_title = l(:field_tracker)
render :template => "reports/issue_report_details"
when "priority"
@field = "priority_id"
@rows = Enumeration::get_values('IPRI')
@data = issues_by_priority
@report_title = l(:field_priority)
render :template => "reports/issue_report_details"
when "category"
@field = "category_id"
@rows = @project.issue_categories
@data = issues_by_category
@report_title = l(:field_category)
render :template => "reports/issue_report_details"
when "author"
@field = "author_id"
@rows = @project.members.collect { |m| m.user }
@data = issues_by_author
@report_title = l(:field_author)
render :template => "reports/issue_report_details"
when "subproject"
@field = "project_id"
@rows = @project.children
@data = issues_by_subproject
@report_title = l(:field_subproject)
render :template => "reports/issue_report_details"
else
@queries = @project.queries.find :all, :conditions => ["is_public=? or user_id=?", true, (logged_in_user ? logged_in_user.id : 0)]
@trackers = Tracker.find(:all, :order => 'position')
@priorities = Enumeration::get_values('IPRI')
@categories = @project.issue_categories
@authors = @project.members.collect { |m| m.user }
@subprojects = @project.children
issues_by_tracker
issues_by_priority
issues_by_category
issues_by_author
issues_by_subproject
@total_hours = @project.time_entries.sum(:hours)
render :template => "reports/issue_report"
end
end
def delays
@trackers = Tracker.find(:all)
if request.get?
@selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
else
@selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
end
@selected_tracker_ids ||= []
@raw =
ActiveRecord::Base.connection.select_all("SELECT datediff( a.created_on, b.created_on ) as delay, count(a.id) as total
FROM issue_histories a, issue_histories b, issues i
WHERE a.status_id =5
AND a.issue_id = b.issue_id
AND a.issue_id = i.id
AND i.tracker_id in (#{@selected_tracker_ids.join(',')})
AND b.id = (
SELECT min( c.id )
FROM issue_histories c
WHERE b.issue_id = c.issue_id )
GROUP BY delay") unless @selected_tracker_ids.empty?
@raw ||=[]
@x_from = 0
@x_to = 0
@y_from = 0
@y_to = 0
@sum_total = 0
@sum_delay = 0
@raw.each do |r|
@x_to = [r['delay'].to_i, @x_to].max
@y_to = [r['total'].to_i, @y_to].max
@sum_total = @sum_total + r['total'].to_i
@sum_delay = @sum_delay + r['total'].to_i * r['delay'].to_i
end
end
private
# Find project of id params[:id]
def find_project
@project = Project.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
def issues_by_tracker
@issues_by_tracker ||=
ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed,
t.id as tracker_id,
count(i.id) as total
from
#{Issue.table_name} i, #{IssueStatus.table_name} s, #{Tracker.table_name} t
where
i.status_id=s.id
and i.tracker_id=t.id
and i.project_id=#{@project.id}
group by s.id, s.is_closed, t.id")
end
def issues_by_priority
@issues_by_priority ||=
ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed,
p.id as priority_id,
count(i.id) as total
from
#{Issue.table_name} i, #{IssueStatus.table_name} s, #{Enumeration.table_name} p
where
i.status_id=s.id
and i.priority_id=p.id
and i.project_id=#{@project.id}
group by s.id, s.is_closed, p.id")
end
def issues_by_category
@issues_by_category ||=
ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed,
c.id as category_id,
count(i.id) as total
from
#{Issue.table_name} i, #{IssueStatus.table_name} s, #{IssueCategory.table_name} c
where
i.status_id=s.id
and i.category_id=c.id
and i.project_id=#{@project.id}
group by s.id, s.is_closed, c.id")
end
def issues_by_author
@issues_by_author ||=
ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed,
a.id as author_id,
count(i.id) as total
from
#{Issue.table_name} i, #{IssueStatus.table_name} s, #{User.table_name} a
where
i.status_id=s.id
and i.author_id=a.id
and i.project_id=#{@project.id}
group by s.id, s.is_closed, a.id")
end
def issues_by_subproject
@issues_by_subproject ||=
ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed,
i.project_id as project_id,
count(i.id) as total
from
#{Issue.table_name} i, #{IssueStatus.table_name} s
where
i.status_id=s.id
and i.project_id IN (#{@project.children.collect{|p| p.id}.join(',')})
group by s.id, s.is_closed, i.project_id") if @project.children.any?
@issues_by_subproject ||= []
end
end

View File

@@ -0,0 +1,208 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'SVG/Graph/Bar'
require 'SVG/Graph/BarHorizontal'
class RepositoriesController < ApplicationController
layout 'base'
before_filter :find_project
before_filter :authorize, :except => [:stats, :graph]
before_filter :check_project_privacy, :only => [:stats, :graph]
def show
# get entries for the browse frame
@entries = @repository.scm.entries('')
show_error and return unless @entries
# check if new revisions have been committed in the repository
scm_latestrev = @entries.revisions.latest
if Setting.autofetch_changesets? && scm_latestrev && ((@repository.latest_changeset.nil?) || (@repository.latest_changeset.revision < scm_latestrev.identifier.to_i))
@repository.fetch_changesets
@repository.reload
end
@changesets = @repository.changesets.find(:all, :limit => 5, :order => "committed_on DESC")
end
def browse
@entries = @repository.scm.entries(@path, @rev)
show_error and return unless @entries
end
def revisions
unless @path == ''
@entry = @repository.scm.entry(@path, @rev)
show_error and return unless @entry
end
@repository.changesets_with_path @path do
@changeset_count = @repository.changesets.count
@changeset_pages = Paginator.new self, @changeset_count,
25,
params['page']
@changesets = @repository.changesets.find(:all,
:limit => @changeset_pages.items_per_page,
:offset => @changeset_pages.current.offset)
end
render :action => "revisions", :layout => false if request.xhr?
end
def entry
if 'raw' == params[:format]
content = @repository.scm.cat(@path, @rev)
show_error and return unless content
send_data content, :filename => @path.split('/').last
end
end
def revision
@changeset = @repository.changesets.find_by_revision(@rev)
show_error and return unless @changeset
end
def diff
@rev_to = params[:rev_to] || (@rev-1)
type = params[:type] || 'inline'
@diff = @repository.scm.diff(params[:path], @rev, @rev_to, type)
show_error and return unless @diff
end
def stats
end
def graph
data = nil
case params[:graph]
when "commits_per_month"
data = graph_commits_per_month(@repository)
when "commits_per_author"
data = graph_commits_per_author(@repository)
end
if data
headers["Content-Type"] = "image/svg+xml"
send_data(data, :type => "image/svg+xml", :disposition => "inline")
else
render_404
end
end
private
def find_project
@project = Project.find(params[:id])
@repository = @project.repository
render_404 and return false unless @repository
@path = params[:path].squeeze('/').gsub(/^\//, '') if params[:path]
@path ||= ''
@rev = params[:rev].to_i if params[:rev] and params[:rev].to_i > 0
rescue ActiveRecord::RecordNotFound
render_404
end
def show_error
flash.now[:notice] = l(:notice_scm_error)
render :nothing => true, :layout => true
end
def graph_commits_per_month(repository)
@date_to = Date.today
@date_from = @date_to << 12
commits_by_day = repository.changesets.count(:all, :group => :commit_date, :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
commits_by_month = [0] * 12
commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
changes_by_day = repository.changes.count(:all, :group => :commit_date)
changes_by_month = [0] * 12
changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
fields = []
month_names = l(:actionview_datehelper_select_month_names_abbr).split(',')
12.times {|m| fields << month_names[((Date.today.month - 1 - m) % 12)]}
graph = SVG::Graph::Bar.new(
:height => 300,
:width => 500,
:fields => fields.reverse,
:stack => :side,
:scale_integers => true,
:step_x_labels => 2,
:show_data_values => false,
:graph_title => l(:label_commits_per_month),
:show_graph_title => true
)
graph.add_data(
:data => commits_by_month[0..11].reverse,
:title => l(:label_revision_plural)
)
graph.add_data(
:data => changes_by_month[0..11].reverse,
:title => l(:label_change_plural)
)
graph.burn
end
def graph_commits_per_author(repository)
commits_by_author = repository.changesets.count(:all, :group => :committer)
commits_by_author.sort! {|x, y| x.last <=> y.last}
changes_by_author = repository.changes.count(:all, :group => :committer)
h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
fields = commits_by_author.collect {|r| r.first}
commits_data = commits_by_author.collect {|r| r.last}
changes_data = commits_by_author.collect {|r| h[r.first] || 0}
fields = fields + [""]*(10 - fields.length) if fields.length<10
commits_data = commits_data + [0]*(10 - commits_data.length) if commits_data.length<10
changes_data = changes_data + [0]*(10 - changes_data.length) if changes_data.length<10
graph = SVG::Graph::BarHorizontal.new(
:height => 300,
:width => 500,
:fields => fields,
:stack => :side,
:scale_integers => true,
:show_data_values => false,
:rotate_y_labels => false,
:graph_title => l(:label_commits_per_author),
:show_graph_title => true
)
graph.add_data(
:data => commits_data,
:title => l(:label_revision_plural)
)
graph.add_data(
:data => changes_data,
:title => l(:label_change_plural)
)
graph.burn
end
end
class Date
def months_ago(date = Date.today)
(date.year - self.year)*12 + (date.month - self.month)
end
def weeks_ago(date = Date.today)
(date.year - self.year)*52 + (date.cweek - self.cweek)
end
end

View File

@@ -1,49 +1,53 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class RolesController < ApplicationController
layout 'base'
before_filter :require_admin
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class RolesController < ApplicationController
layout 'base'
before_filter :require_admin
verify :method => :post, :only => [ :destroy, :move ],
:redirect_to => { :action => :list }
def index
list
render :action => 'list'
render :action => 'list' unless request.xhr?
end
def list
@role_pages, @roles = paginate :roles, :per_page => 10
@role_pages, @roles = paginate :roles, :per_page => 25, :order => "position"
render :action => "list", :layout => false if request.xhr?
end
def new
@role = Role.new(params[:role])
@role = Role.new(params[:role])
if request.post?
@role.permissions = Permission.find(@params[:permission_ids]) if @params[:permission_ids]
@role.permissions = Permission.find(params[:permission_ids]) if params[:permission_ids]
if @role.save
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list'
end
end
end
@permissions = Permission.find(:all, :conditions => ["is_public=?", false], :order => 'sort ASC')
end
def edit
@role = Role.find(params[:id])
@role = Role.find(params[:id])
if request.post? and @role.update_attributes(params[:role])
@role.permissions = Permission.find(@params[:permission_ids] || [])
@role.permissions = Permission.find(params[:permission_ids] || [])
Permission.allowed_to_role_expired
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'list'
@@ -52,32 +56,60 @@ class RolesController < ApplicationController
end
def destroy
@role = Role.find(params[:id])
unless @role.members.empty?
flash[:notice] = 'Some members have this role. Can\'t delete it.'
else
@role.destroy
@role = Role.find(params[:id])
unless @role.members.empty?
flash[:notice] = 'Some members have this role. Can\'t delete it.'
else
@role.destroy
end
redirect_to :action => 'list'
end
def workflow
@role = Role.find_by_id(params[:role_id])
@tracker = Tracker.find_by_id(params[:tracker_id])
if request.post?
Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
(params[:issue_status] || []).each { |old, news|
news.each { |new|
@role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new)
}
}
if @role.save
flash[:notice] = l(:notice_successful_update)
end
end
@roles = Role.find_all
@trackers = Tracker.find_all
@statuses = IssueStatus.find(:all, :include => :workflows)
end
def move
@role = Role.find(params[:id])
case params[:position]
when 'highest'
@role.move_to_top
when 'higher'
@role.move_higher
when 'lower'
@role.move_lower
when 'lowest'
@role.move_to_bottom
end if params[:position]
redirect_to :action => 'list'
end
def workflow
@role = Role.find_by_id(params[:role_id])
@tracker = Tracker.find_by_id(params[:tracker_id])
if request.post?
Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
(params[:issue_status] || []).each { |old, news|
news.each { |new|
@role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new)
}
}
if @role.save
flash[:notice] = l(:notice_successful_update)
end
end
@roles = Role.find(:all, :order => 'position')
@trackers = Tracker.find(:all, :order => 'position')
@statuses = IssueStatus.find(:all, :include => :workflows, :order => 'position')
end
def report
@roles = Role.find(:all, :order => 'position')
@permissions = Permission.find :all, :conditions => ["is_public=?", false], :order => 'sort'
if request.post?
@roles.each do |role|
role.permissions = Permission.find(params[:permission_ids] ? (params[:permission_ids][role.id.to_s] || []) : [] )
end
Permission.allowed_to_role_expired
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'list'
end
end
end

View File

@@ -0,0 +1,33 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class SettingsController < ApplicationController
layout 'base'
before_filter :require_admin
def index
edit
render :action => 'edit'
end
def edit
if request.post? and params[:settings] and params[:settings].is_a? Hash
params[:settings].each { |name, value| Setting[name] = value }
redirect_to :action => 'edit' and return
end
end
end

View File

@@ -0,0 +1,44 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class SysController < ActionController::Base
wsdl_service_name 'Sys'
web_service_api SysApi
web_service_scaffold :invoke
before_invocation :check_enabled
def projects
Project.find(:all, :include => :repository)
end
def repository_created(project_id, url)
project = Project.find_by_id(project_id)
return 0 unless project && project.repository.nil?
logger.debug "Repository for #{project.name} created"
repository = Repository.new(:project => project, :url => url)
repository.root_url = url
repository.save
repository.id
end
protected
def check_enabled(name, args)
Setting.sys_api_enabled?
end
end

View File

@@ -0,0 +1,80 @@
class TimelogController < ApplicationController
layout 'base'
before_filter :find_project
before_filter :authorize, :only => :edit
before_filter :check_project_privacy, :only => :details
helper :sort
include SortHelper
def details
sort_init 'spent_on', 'desc'
sort_update
@entries = (@issue ? @issue : @project).time_entries.find(:all, :include => [:activity, :user, {:issue => [:tracker, :assigned_to, :priority]}], :order => sort_clause)
@total_hours = @entries.inject(0) { |sum,entry| sum + entry.hours }
@owner_id = logged_in_user ? logged_in_user.id : 0
send_csv and return if 'csv' == params[:export]
render :action => 'details', :layout => false if request.xhr?
end
def edit
render_404 and return if @time_entry && @time_entry.user != logged_in_user
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
@time_entry.attributes = params[:time_entry]
if request.post? and @time_entry.save
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'details', :project_id => @time_entry.project, :issue_id => @time_entry.issue
return
end
@activities = Enumeration::get_values('ACTI')
end
private
def find_project
if params[:id]
@time_entry = TimeEntry.find(params[:id])
@project = @time_entry.project
elsif params[:issue_id]
@issue = Issue.find(params[:issue_id])
@project = @issue.project
elsif params[:project_id]
@project = Project.find(params[:project_id])
else
render_404
return false
end
end
def send_csv
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
export = StringIO.new
CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
# csv header fields
headers = [l(:field_spent_on),
l(:field_user),
l(:field_activity),
l(:field_issue),
l(:field_hours),
l(:field_comment)
]
csv << headers.collect {|c| ic.iconv(c) }
# csv lines
@entries.each do |entry|
fields = [l_date(entry.spent_on),
entry.user.name,
entry.activity.name,
(entry.issue ? entry.issue.id : nil),
entry.hours,
entry.comment
]
csv << fields.collect {|c| ic.iconv(c.to_s) }
end
end
export.rewind
send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
end
end

View File

@@ -1,42 +1,50 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class TrackersController < ApplicationController
layout 'base'
before_filter :require_admin
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class TrackersController < ApplicationController
layout 'base'
before_filter :require_admin
def index
list
render :action => 'list'
render :action => 'list' unless request.xhr?
end
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :list }
verify :method => :post, :only => [ :destroy, :move ], :redirect_to => { :action => :list }
def list
@tracker_pages, @trackers = paginate :trackers, :per_page => 10
@tracker_pages, @trackers = paginate :trackers, :per_page => 10, :order => 'position'
render :action => "list", :layout => false if request.xhr?
end
def new
@tracker = Tracker.new(params[:tracker])
if request.post? and @tracker.save
# workflow copy
if params[:copy_workflow_from] && (copy_from = Tracker.find_by_id(params[:copy_workflow_from]))
copy_from.workflows.each do |w|
@tracker.workflows << w.clone
end
end
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list'
end
@trackers = Tracker.find :all
end
def edit
@@ -47,14 +55,28 @@ class TrackersController < ApplicationController
end
end
def move
@tracker = Tracker.find(params[:id])
case params[:position]
when 'highest'
@tracker.move_to_top
when 'higher'
@tracker.move_higher
when 'lower'
@tracker.move_lower
when 'lowest'
@tracker.move_to_bottom
end if params[:position]
redirect_to :action => 'list'
end
def destroy
@tracker = Tracker.find(params[:id])
unless @tracker.issues.empty?
flash[:notice] = "This tracker contains issues and can\'t be deleted."
else
@tracker.destroy
@tracker = Tracker.find(params[:id])
unless @tracker.issues.empty?
flash[:notice] = "This tracker contains issues and can\'t be deleted."
else
@tracker.destroy
end
redirect_to :action => 'list'
end
end
end

View File

@@ -1,88 +1,119 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class UsersController < ApplicationController
layout 'base'
before_filter :require_admin
helper :sort
include SortHelper
helper :custom_fields
include CustomFieldsHelper
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class UsersController < ApplicationController
layout 'base'
before_filter :require_admin
helper :sort
include SortHelper
helper :custom_fields
include CustomFieldsHelper
def index
list
render :action => 'list'
render :action => 'list' unless request.xhr?
end
def list
sort_init 'login', 'asc'
sort_update
@user_count = User.count
@user_pages = Paginator.new self, @user_count,
15,
@params['page']
@users = User.find :all,:order => sort_clause,
:limit => @user_pages.items_per_page,
:offset => @user_pages.current.offset
def list
sort_init 'login', 'asc'
sort_update
@status = params[:status] ? params[:status].to_i : 1
conditions = nil
conditions = ["status=?", @status] unless @status == 0
@user_count = User.count(:conditions => conditions)
@user_pages = Paginator.new self, @user_count,
15,
params['page']
@users = User.find :all,:order => sort_clause,
:conditions => conditions,
:limit => @user_pages.items_per_page,
:offset => @user_pages.current.offset
render :action => "list", :layout => false if request.xhr?
end
def add
if request.get?
@user = User.new(:language => $RDM_DEFAULT_LANG)
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
if request.get?
@user = User.new(:language => Setting.default_language)
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
else
@user = User.new(params[:user])
@user.admin = params[:user][:admin] || false
@user.login = params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values
@user = User.new(params[:user])
@user.admin = params[:user][:admin] || false
@user.login = params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values
if @user.save
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list'
end
end
end
@auth_sources = AuthSource.find(:all)
end
def edit
@user = User.find(params[:id])
if request.get?
@custom_values = UserCustomField.find(:all).collect { |x| @user.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
else
@user.admin = params[:user][:admin] if params[:user][:admin]
@user.login = params[:user][:login] if params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty?
if params[:custom_fields]
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values
end
if request.get?
@custom_values = UserCustomField.find(:all).collect { |x| @user.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
else
@user.admin = params[:user][:admin] if params[:user][:admin]
@user.login = params[:user][:login] if params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty? or @user.auth_source_id
if params[:custom_fields]
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values
end
if @user.update_attributes(params[:user])
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'list'
end
end
end
@auth_sources = AuthSource.find(:all)
@roles = Role.find(:all, :order => 'position')
@projects = Project.find(:all) - @user.projects
@membership ||= Member.new
end
def edit_membership
@user = User.find(params[:id])
@membership = params[:membership_id] ? Member.find(params[:membership_id]) : Member.new(:user => @user)
@membership.attributes = params[:membership]
if request.post? and @membership.save
flash[:notice] = l(:notice_successful_update)
end
redirect_to :action => 'edit', :id => @user and return
end
def destroy_membership
@user = User.find(params[:id])
if request.post? and Member.find(params[:membership_id]).destroy
flash[:notice] = l(:notice_successful_update)
end
redirect_to :action => 'edit', :id => @user and return
end
def destroy
User.find(params[:id]).destroy
redirect_to :action => 'list'
rescue
flash[:notice] = "Unable to delete user"
redirect_to :action => 'list'
end
rescue
flash[:notice] = "Unable to delete user"
redirect_to :action => 'list'
end
end

View File

@@ -1,57 +1,58 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class VersionsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class VersionsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
def edit
if request.post? and @version.update_attributes(params[:version])
flash[:notice] = l(:notice_successful_update)
redirect_to :controller => 'projects', :action => 'settings', :id => @project
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
end
end
def destroy
def destroy
@version.destroy
redirect_to :controller => 'projects', :action => 'settings', :id => @project
rescue
flash[:notice] = "Unable to delete version"
redirect_to :controller => 'projects', :action => 'settings', :id => @project
end
def download
@attachment = @version.attachments.find(params[:attachment_id])
@attachment.increment_download
send_file @attachment.diskfile, :filename => @attachment.filename
rescue
flash[:notice] = l(:notice_file_not_found)
redirect_to :controller => 'projects', :action => 'list_files', :id => @project
end
def destroy_file
@version.attachments.find(params[:attachment_id]).destroy
flash[:notice] = l(:notice_successful_delete)
redirect_to :controller => 'projects', :action => 'list_files', :id => @project
end
private
def find_project
@version = Version.find(params[:id])
@project = @version.project
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
rescue
flash[:notice] = "Unable to delete version"
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
end
def download
@attachment = @version.attachments.find(params[:attachment_id])
@attachment.increment_download
send_file @attachment.diskfile, :filename => @attachment.filename
rescue
render_404
end
def destroy_file
@version.attachments.find(params[:attachment_id]).destroy
flash[:notice] = l(:notice_successful_delete)
redirect_to :controller => 'projects', :action => 'list_files', :id => @project
end
private
def find_project
@version = Version.find(params[:id])
@project = @version.project
rescue ActiveRecord::RecordNotFound
render_404
end
end

View File

@@ -1,25 +1,25 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class WelcomeController < ApplicationController
layout 'base'
def index
@news = News.latest
@projects = Project.latest
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class WelcomeController < ApplicationController
layout 'base'
def index
@news = News.latest logged_in_user
@projects = Project.latest logged_in_user
end
end

View File

@@ -0,0 +1,112 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class WikiController < ApplicationController
layout 'base'
before_filter :find_wiki, :check_project_privacy, :except => [:preview]
# display a page (in editing mode if it doesn't exist)
def index
page_title = params[:page]
@page = @wiki.find_or_new_page(page_title)
if @page.new_record?
edit
render :action => 'edit' and return
end
@content = @page.content_for_version(params[:version])
if params[:export] == 'html'
export = render_to_string :action => 'export', :layout => false
send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
return
elsif params[:export] == 'txt'
send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
return
end
render :action => 'show'
end
# edit an existing page or a new one
def edit
@page = @wiki.find_or_new_page(params[:page])
@page.content = WikiContent.new(:page => @page) if @page.new_record?
@content = @page.content_for_version(params[:version])
@content.text = "h1. #{@page.pretty_title}" if @content.text.blank?
# don't keep previous comment
@content.comment = nil
if request.post?
if @content.text == params[:content][:text]
# don't save if text wasn't changed
redirect_to :action => 'index', :id => @project, :page => @page.title
return
end
@content.text = params[:content][:text]
@content.comment = params[:content][:comment]
@content.author = logged_in_user
# if page is new @page.save will also save content, but not if page isn't a new record
if (@page.new_record? ? @page.save : @content.save)
redirect_to :action => 'index', :id => @project, :page => @page.title
end
end
end
# show page history
def history
@page = @wiki.find_page(params[:page])
# don't load text
@versions = @page.content.versions.find :all,
:select => "id, author_id, comment, updated_on, version",
:order => 'version DESC'
end
# display special pages
def special
page_title = params[:page].downcase
case page_title
# show pages index, sorted by title
when 'page_index'
# eager load information about last updates, without loading text
@pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
:joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
:order => 'title'
# export wiki to a single html file
when 'export'
@pages = @wiki.pages.find :all, :order => 'title'
export = render_to_string :action => 'export_multiple', :layout => false
send_data(export, :type => 'text/html', :filename => "wiki.html")
return
else
# requested special page doesn't exist, redirect to default page
redirect_to :action => 'index', :id => @project, :page => nil and return
end
render :action => "special_#{page_title}"
end
def preview
@text = params[:content][:text]
render :partial => 'preview'
end
private
def find_wiki
@project = Project.find(params[:id])
@wiki = @project.wiki
rescue ActiveRecord::RecordNotFound
render_404
end
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module AccountHelper
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module AdminHelper
end

View File

@@ -1,156 +1,241 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ApplicationHelper
# Return current logged in user or nil
def loggedin?
@logged_in_user
end
# Return true if user is logged in and is admin, otherwise false
def admin_loggedin?
@logged_in_user and @logged_in_user.admin?
end
# Return true if user is authorized for controller/action, otherwise false
def authorize_for(controller, action)
# check if action is allowed on public projects
if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ controller, action ]
return true
end
# check if user is authorized
if @logged_in_user and (@logged_in_user.admin? or Permission.allowed_to_role( "%s/%s" % [ controller, action ], @logged_in_user.role_for_project(@project.id) ) )
return true
end
return false
end
# Display a link if user is authorized
def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller], options[:action])
end
# Display a link to user's account page
def link_to_user(user)
link_to user.display_name, :controller => 'account', :action => 'show', :id => user
end
def format_date(date)
l_date(date) if date
end
def format_time(time)
l_datetime(time) if time
end
def pagination_links_full(paginator, options={}, html_options={})
html =''
html << link_to(('&#171; ' + l(:label_previous) ), { :page => paginator.current.previous }) + ' ' if paginator.current.previous
html << (pagination_links(paginator, options, html_options) || '')
html << ' ' + link_to((l(:label_next) + ' &#187;'), { :page => paginator.current.next }) if paginator.current.next
html
end
def error_messages_for(object_name, options = {})
options = options.symbolize_keys
object = instance_variable_get("@#{object_name}")
if object && !object.errors.empty?
# build full_messages here with controller current language
full_messages = []
object.errors.each do |attr, msg|
next if msg.nil?
if attr == "base"
full_messages << l(msg)
else
full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(msg) unless attr == "custom_values"
end
end
# retrieve custom values error messages
if object.errors[:custom_values]
object.custom_values.each do |v|
v.errors.each do |attr, msg|
next if msg.nil?
full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(msg)
end
end
end
content_tag("div",
content_tag(
options[:header_tag] || "h2", lwr(:gui_validation_error, full_messages.length) + " :"
) +
content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }),
"id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
)
else
""
end
end
def lang_options_for_select
(GLoc.valid_languages.sort {|x,y| x.to_s <=> y.to_s }).collect {|lang| [ l_lang_name(lang.to_s, lang), lang.to_s]}
end
def label_tag_for(name, option_tags = nil, options = {})
label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
content_tag("label", label_text)
end
def labelled_tabular_form_for(name, object, options, &proc)
options[:html] ||= {}
options[:html].store :class, "tabular"
form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
end
def check_all_links(form_name)
link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
" | " +
link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
end
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ApplicationHelper
# Return current logged in user or nil
def loggedin?
@logged_in_user
end
# Return true if user is logged in and is admin, otherwise false
def admin_loggedin?
@logged_in_user and @logged_in_user.admin?
end
# Return true if user is authorized for controller/action, otherwise false
def authorize_for(controller, action)
# check if action is allowed on public projects
if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ controller, action ]
return true
end
# check if user is authorized
if @logged_in_user and (@logged_in_user.admin? or Permission.allowed_to_role( "%s/%s" % [ controller, action ], @logged_in_user.role_for_project(@project) ) )
return true
end
return false
end
# Display a link if user is authorized
def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller], options[:action])
end
# Display a link to user's account page
def link_to_user(user)
link_to user.display_name, :controller => 'account', :action => 'show', :id => user
end
def link_to_issue(issue)
link_to "#{issue.tracker.name} ##{issue.id}", :controller => "issues", :action => "show", :id => issue
end
def toggle_link(name, id, options={})
onclick = "Element.toggle('#{id}'); "
onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
onclick << "return false;"
link_to(name, "#", :onclick => onclick)
end
def image_to_function(name, function, html_options = {})
html_options.symbolize_keys!
tag(:input, html_options.merge({
:type => "image", :src => image_path(name),
:onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
}))
end
def format_date(date)
l_date(date) if date
end
def format_time(time)
l_datetime((time.is_a? String) ? time.to_time : time) if time
end
def day_name(day)
l(:general_day_names).split(',')[day-1]
end
def month_name(month)
l(:actionview_datehelper_select_month_names).split(',')[month-1]
end
def pagination_links_full(paginator, options={}, html_options={})
html = ''
html << link_to_remote(('&#171; ' + l(:label_previous)),
{:update => "content", :url => options.merge(:page => paginator.current.previous)},
{:href => url_for(:params => options.merge(:page => paginator.current.previous))}) + ' ' if paginator.current.previous
html << (pagination_links_each(paginator, options) do |n|
link_to_remote(n.to_s,
{:url => {:params => options.merge(:page => n)}, :update => 'content'},
{:href => url_for(:params => options.merge(:page => n))})
end || '')
html << ' ' + link_to_remote((l(:label_next) + ' &#187;'),
{:update => "content", :url => options.merge(:page => paginator.current.next)},
{:href => url_for(:params => options.merge(:page => paginator.current.next))}) if paginator.current.next
html
end
# textilize text according to system settings and RedCloth availability
def textilizable(text, options = {})
# different methods for formatting wiki links
case options[:wiki_links]
when :local
# used for local links to html files
format_wiki_link = Proc.new {|title| "#{title}.html" }
when :anchor
# used for single-file wiki export
format_wiki_link = Proc.new {|title| "##{title}" }
else
if @project
format_wiki_link = Proc.new {|title| url_for :controller => 'wiki', :action => 'index', :id => @project, :page => title }
else
format_wiki_link = Proc.new {|title| title }
end
end
# turn wiki links into textile links:
# example:
# [[link]] -> "link":link
# [[link|title]] -> "title":link
text = text.gsub(/\[\[([^\]\|]+)(\|([^\]\|]+))?\]\]/) {|m| "\"#{$3 || $1}\":" + format_wiki_link.call(Wiki.titleize($1)) }
# turn issue ids to textile links
# example:
# #52 -> "#52":/issues/show/52
text = text.gsub(/#(\d+)(?=\b)/) {|m| "\"##{$1}\":" + url_for(:controller => 'issues', :action => 'show', :id => $1) }
# turn revision ids to textile links (@project needed)
# example:
# r52 -> "r52":/repositories/revision/6?rev=52 (@project.id is 6)
text = text.gsub(/(?=\b)r(\d+)(?=\b)/) {|m| "\"r#{$1}\":" + url_for(:controller => 'repositories', :action => 'revision', :id => @project.id, :rev => $1) } if @project
# finally textilize text
@do_textilize ||= (Setting.text_formatting == 'textile') && (ActionView::Helpers::TextHelper.method_defined? "textilize")
text = @do_textilize ? auto_link(RedCloth.new(text).to_html) : simple_format(auto_link(h(text)))
end
def error_messages_for(object_name, options = {})
options = options.symbolize_keys
object = instance_variable_get("@#{object_name}")
if object && !object.errors.empty?
# build full_messages here with controller current language
full_messages = []
object.errors.each do |attr, msg|
next if msg.nil?
msg = msg.first if msg.is_a? Array
if attr == "base"
full_messages << l(msg)
else
full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(msg) unless attr == "custom_values"
end
end
# retrieve custom values error messages
if object.errors[:custom_values]
object.custom_values.each do |v|
v.errors.each do |attr, msg|
next if msg.nil?
msg = msg.first if msg.is_a? Array
full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(msg)
end
end
end
content_tag("div",
content_tag(
options[:header_tag] || "h2", lwr(:gui_validation_error, full_messages.length) + " :"
) +
content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }),
"id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
)
else
""
end
end
def lang_options_for_select(blank=true)
(blank ? [["(auto)", ""]] : []) +
(GLoc.valid_languages.sort {|x,y| x.to_s <=> y.to_s }).collect {|lang| [ l_lang_name(lang.to_s, lang), lang.to_s]}
end
def label_tag_for(name, option_tags = nil, options = {})
label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
content_tag("label", label_text)
end
def labelled_tabular_form_for(name, object, options, &proc)
options[:html] ||= {}
options[:html].store :class, "tabular"
form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
end
def check_all_links(form_name)
link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
" | " +
link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
end
def calendar_for(field_id)
image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
end
end
class TabularFormBuilder < ActionView::Helpers::FormBuilder
include GLoc
def initialize(object_name, object, template, options, proc)
set_language_if_valid options.delete(:lang)
@object_name, @object, @template, @options, @proc = object_name, object, template, options, proc
end
(field_helpers - %w(radio_button) + %w(date_select)).each do |selector|
src = <<-END_SRC
def #{selector}(field, options = {})
label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
label = @template.content_tag("label", label_text,
:class => (@object.errors[field] ? "error" : nil),
:for => (@object_name.to_s + "_" + field.to_s))
label + super
end
END_SRC
class_eval src, __FILE__, __LINE__
end
def select(field, choices, options = {})
label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
label = @template.content_tag("label", label_text,
:class => (@object.errors[field] ? "error" : nil),
:for => (@object_name.to_s + "_" + field.to_s))
label + super
end
end
class TabularFormBuilder < ActionView::Helpers::FormBuilder
include GLoc
def initialize(object_name, object, template, options, proc)
set_language_if_valid options.delete(:lang)
@object_name, @object, @template, @options, @proc = object_name, object, template, options, proc
end
(field_helpers - %w(radio_button hidden_field) + %w(date_select)).each do |selector|
src = <<-END_SRC
def #{selector}(field, options = {})
return super if options.delete :no_label
label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
label = @template.content_tag("label", label_text,
:class => (@object && @object.errors[field] ? "error" : nil),
:for => (@object_name.to_s + "_" + field.to_s))
label + super
end
END_SRC
class_eval src, __FILE__, __LINE__
end
def select(field, choices, options = {}, html_options = {})
label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
label = @template.content_tag("label", label_text,
:class => (@object && @object.errors[field] ? "error" : nil),
:for => (@object_name.to_s + "_" + field.to_s))
label + super
end
end

View File

@@ -1,65 +1,77 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module CustomFieldsHelper
# Return custom field html tag corresponding to its format
def custom_field_tag(custom_value)
custom_field = custom_value.custom_field
field_name = "custom_fields[#{custom_field.id}]"
field_id = "custom_fields_#{custom_field.id}"
case custom_field.field_format
when "string", "int", "date"
text_field 'custom_value', 'value', :name => field_name, :id => field_id
when "text"
text_area 'custom_value', 'value', :name => field_name, :id => field_id, :cols => 60, :rows => 3
when "bool"
check_box 'custom_value', 'value', :name => field_name, :id => field_id
when "list"
select 'custom_value', 'value', custom_field.possible_values.split('|'), { :include_blank => true }, :name => field_name, :id => field_id
end
end
# Return custom field label tag
def custom_field_label_tag(custom_value)
content_tag "label", custom_value.custom_field.name +
(custom_value.custom_field.is_required? ? " <span class=\"required\">*</span>" : ""),
:for => "custom_fields_#{custom_value.custom_field.id}",
:class => (custom_value.errors.empty? ? nil : "error" )
end
# Return custom field tag with its label tag
def custom_field_tag_with_label(custom_value)
custom_field_label_tag(custom_value) + custom_field_tag(custom_value)
end
# Return a string used to display a custom value
def show_value(custom_value)
case custom_value.custom_field.field_format
when "bool"
l_YesNo(custom_value.value == "1")
else
custom_value.value
end
end
# Return an array of custom field formats which can be used in select_tag
def custom_field_formats_for_select
CustomField::FIELD_FORMATS.keys.collect { |k| [ l(CustomField::FIELD_FORMATS[k]), k ] }
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module CustomFieldsHelper
# Return custom field html tag corresponding to its format
def custom_field_tag(custom_value)
custom_field = custom_value.custom_field
field_name = "custom_fields[#{custom_field.id}]"
field_id = "custom_fields_#{custom_field.id}"
case custom_field.field_format
when "string", "int"
text_field 'custom_value', 'value', :name => field_name, :id => field_id
when "date"
text_field('custom_value', 'value', :name => field_name, :id => field_id, :size => 10) +
calendar_for(field_id)
when "text"
text_area 'custom_value', 'value', :name => field_name, :id => field_id, :cols => 60, :rows => 3
when "bool"
check_box 'custom_value', 'value', :name => field_name, :id => field_id
when "list"
select 'custom_value', 'value', custom_field.possible_values, { :include_blank => true }, :name => field_name, :id => field_id
end
end
# Return custom field label tag
def custom_field_label_tag(custom_value)
content_tag "label", custom_value.custom_field.name +
(custom_value.custom_field.is_required? ? " <span class=\"required\">*</span>" : ""),
:for => "custom_fields_#{custom_value.custom_field.id}",
:class => (custom_value.errors.empty? ? nil : "error" )
end
# Return custom field tag with its label tag
def custom_field_tag_with_label(custom_value)
custom_field_label_tag(custom_value) + custom_field_tag(custom_value)
end
# Return a string used to display a custom value
def show_value(custom_value)
return "" unless custom_value
format_value(custom_value.value, custom_value.custom_field.field_format)
end
# Return a string used to display a custom value
def format_value(value, field_format)
return "" unless value && !value.empty?
case field_format
when "date"
begin; l_date(value.to_date); rescue; value end
when "bool"
l_YesNo(value == "1")
else
value
end
end
# Return an array of custom field formats which can be used in select_tag
def custom_field_formats_for_select
CustomField::FIELD_FORMATS.sort {|a,b| a[1][:order]<=>b[1][:order]}.collect { |k| [ l(k[1][:name]), k[0] ] }
end
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module DocumentsHelper
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module EnumerationsHelper
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module IssuesHelper
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module FeedsHelper
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module HelpHelper
end

View File

@@ -0,0 +1,75 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'iconv'
require 'rfpdf/chinese'
module IfpdfHelper
class IFPDF < FPDF
include GLoc
attr_accessor :footer_date
def initialize(lang)
super()
set_language_if_valid lang
case current_language
when :ja
extend(PDF_Japanese)
AddSJISFont()
@font_for_content = 'SJIS'
@font_for_footer = 'SJIS'
when :zh
extend(PDF_Chinese)
AddBig5Font()
@font_for_content = 'Big5'
@font_for_footer = 'Big5'
else
@font_for_content = 'Arial'
@font_for_footer = 'Helvetica'
end
SetCreator("redMine #{Redmine::VERSION}")
SetFont(@font_for_content)
end
def SetFontStyle(style, size)
SetFont(@font_for_content, style, size)
end
def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
@ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')
txt = begin
@ic.iconv(txt)
rescue
txt
end
super w,h,txt,border,ln,align,fill,link
end
def Footer
SetFont(@font_for_footer, 'I', 8)
SetY(-15)
SetX(15)
Cell(0, 5, @footer_date, 0, 0, 'L')
SetY(-15)
SetX(-30)
Cell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
end
end
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module IssueCategoriesHelper
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module IssueStatusesHelper
end

View File

@@ -0,0 +1,86 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module IssuesHelper
def show_detail(detail, no_html=false)
case detail.property
when 'attr'
label = l(("field_" + detail.prop_key.to_s.gsub(/\_id$/, "")).to_sym)
case detail.prop_key
when 'due_date', 'start_date'
value = format_date(detail.value.to_date) if detail.value
old_value = format_date(detail.old_value.to_date) if detail.old_value
when 'status_id'
s = IssueStatus.find_by_id(detail.value) and value = s.name if detail.value
s = IssueStatus.find_by_id(detail.old_value) and old_value = s.name if detail.old_value
when 'assigned_to_id'
u = User.find_by_id(detail.value) and value = u.name if detail.value
u = User.find_by_id(detail.old_value) and old_value = u.name if detail.old_value
when 'priority_id'
e = Enumeration.find_by_id(detail.value) and value = e.name if detail.value
e = Enumeration.find_by_id(detail.old_value) and old_value = e.name if detail.old_value
when 'category_id'
c = IssueCategory.find_by_id(detail.value) and value = c.name if detail.value
c = IssueCategory.find_by_id(detail.old_value) and old_value = c.name if detail.old_value
when 'fixed_version_id'
v = Version.find_by_id(detail.value) and value = v.name if detail.value
v = Version.find_by_id(detail.old_value) and old_value = v.name if detail.old_value
end
when 'cf'
custom_field = CustomField.find_by_id(detail.prop_key)
if custom_field
label = custom_field.name
value = format_value(detail.value, custom_field.field_format) if detail.value
old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value
end
when 'attachment'
label = l(:label_attachment)
end
label ||= detail.prop_key
value ||= detail.value
old_value ||= detail.old_value
unless no_html
label = content_tag('strong', label)
old_value = content_tag("i", h(old_value)) if detail.old_value
old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?)
value = content_tag("i", h(value)) if value
end
if detail.value and !detail.value.to_s.empty?
case detail.property
when 'attr', 'cf'
if old_value
label + " " + l(:text_journal_changed, old_value, value)
else
label + " " + l(:text_journal_set_to, value)
end
when 'attachment'
"#{label} #{value} #{l(:label_added)}"
end
else
case detail.property
when 'attr', 'cf'
label + " " + l(:text_journal_deleted) + " (#{old_value})"
when 'attachment'
"#{label} #{old_value} #{l(:label_deleted)}"
end
end
end
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module MembersHelper
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ProjectsHelper
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module MyHelper
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module NewsHelper
end

View File

@@ -0,0 +1,29 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ProjectsHelper
def highlight_tokens(text, tokens)
return text unless tokens && !tokens.empty?
regexp = Regexp.new "(#{tokens.join('|')})", Regexp::IGNORECASE
result = ''
text.split(regexp).each_with_index do |words, i|
result << (i.even? ? (words.length > 100 ? "#{words[0..44]} ... #{words[-45..-1]}" : words) : content_tag('span', words, :class => 'highlight'))
end
result
end
end

View File

@@ -0,0 +1,6 @@
module QueriesHelper
def operators_for_select(filter_type)
Query.operators_by_filter_type[filter_type].collect {|o| [l(Query.operators[o]), o]}
end
end

View File

@@ -1,32 +1,32 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ReportsHelper
def aggregate(data, criteria)
a = 0
data.each { |row|
match = 1
criteria.each { |k, v|
match = 0 unless row[k].to_s == v.to_s
} unless criteria.nil?
a = a + row["total"].to_i if match == 1
} unless data.nil?
a
end
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ReportsHelper
def aggregate(data, criteria)
a = 0
data.each { |row|
match = 1
criteria.each { |k, v|
match = 0 unless row[k].to_s == v.to_s
} unless criteria.nil?
a = a + row["total"].to_i if match == 1
} unless data.nil?
a
end
end

View File

@@ -0,0 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module RepositoriesHelper
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module RolesHelper
end

View File

@@ -0,0 +1,19 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module SettingsHelper
end

View File

@@ -61,7 +61,7 @@ module SortHelper
# defaults to '<controller_name>_sort'.
#
def sort_init(default_key, default_order='asc', name=nil)
@sort_name = name || @params[:controller] + @params[:action] + '_sort'
@sort_name = name || params[:controller] + params[:action] + '_sort'
@sort_default = {:key => default_key, :order => default_order}
end
@@ -69,21 +69,21 @@ module SortHelper
# sort_clause.
#
def sort_update()
if @params[:sort_key]
sort = {:key => @params[:sort_key], :order => @params[:sort_order]}
elsif @session[@sort_name]
sort = @session[@sort_name] # Previous sort.
if params[:sort_key]
sort = {:key => params[:sort_key], :order => params[:sort_order]}
elsif session[@sort_name]
sort = session[@sort_name] # Previous sort.
else
sort = @sort_default
end
@session[@sort_name] = sort
session[@sort_name] = sort
end
# Returns an SQL sort clause corresponding to the current sort state.
# Use this to sort the controller's table items collection.
#
def sort_clause()
@session[@sort_name][:key] + ' ' + @session[@sort_name][:order]
session[@sort_name][:key] + ' ' + session[@sort_name][:order]
end
# Returns a link which sorts by the named column.
@@ -93,13 +93,13 @@ module SortHelper
# - A sort icon image is positioned to the right of the sort link.
#
def sort_link(column, caption=nil)
key, order = @session[@sort_name][:key], @session[@sort_name][:order]
key, order = session[@sort_name][:key], session[@sort_name][:order]
if key == column
if order.downcase == 'asc'
icon = 'sort_asc'
icon = 'sort_asc.png'
order = 'desc'
else
icon = 'sort_desc'
icon = 'sort_desc.png'
order = 'asc'
end
else
@@ -107,8 +107,13 @@ module SortHelper
order = 'desc' # changed for desc order by default
end
caption = titleize(Inflector::humanize(column)) unless caption
params = {:params => {:sort_key => column, :sort_order => order}}
link_to(caption, params) + (icon ? nbsp(2) + image_tag(icon) : '')
url = {:sort_key => column, :sort_order => order, :issue_id => params[:issue_id], :project_id => params[:project_id]}
link_to_remote(caption,
{:update => "content", :url => url},
{:href => url_for(url)}) +
(icon ? nbsp(2) + image_tag(icon) : '')
end
# Returns a table header <th> tag with a sort link for the named column

View File

@@ -0,0 +1,2 @@
module TimelogHelper
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module TrackersHelper
end

View File

@@ -1,19 +1,25 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module UsersHelper
def status_options_for_select(selected)
options_for_select([[l(:label_all), "*"],
[l(:status_active), 1],
[l(:status_registered), 2],
[l(:status_locked), 3]], selected)
end
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module VersionsHelper
end

View File

@@ -1,19 +1,19 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module WelcomeHelper
end

View File

@@ -0,0 +1,19 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module WikiHelper
end

View File

@@ -1,81 +1,92 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require "digest/md5"
class Attachment < ActiveRecord::Base
belongs_to :container, :polymorphic => true
belongs_to :author, :class_name => "User", :foreign_key => "author_id"
validates_presence_of :filename
def file=(incomming_file)
unless incomming_file.nil?
@temp_file = incomming_file
if @temp_file.size > 0
self.filename = sanitize_filename(@temp_file.original_filename)
self.disk_filename = DateTime.now.strftime("%y%m%d%H%M%S") + "_" + self.filename
self.content_type = @temp_file.content_type
self.filesize = @temp_file.size
end
end
end
# Copy temp file to its final location
def before_save
if @temp_file && (@temp_file.size > 0)
logger.debug("saving '#{self.diskfile}'")
File.open(diskfile, "wb") do |f|
f.write(@temp_file.read)
end
self.digest = Digest::MD5.hexdigest(File.read(diskfile))
end
end
# Deletes file on the disk
def after_destroy
if self.filename?
File.delete(diskfile) if File.exist?(diskfile)
end
end
# Returns file's location on disk
def diskfile
"#{$RDM_STORAGE_PATH}/#{self.disk_filename}"
end
def increment_download
increment!(:downloads)
end
# returns last created projects
def self.most_downloaded
find(:all, :limit => 5, :order => "downloads DESC")
end
private
def sanitize_filename(value)
# get only the filename, not the whole path
just_filename = value.gsub(/^.*(\\|\/)/, '')
# NOTE: File.basename doesn't work right with Windows paths on Unix
# INCORRECT: just_filename = File.basename(value.gsub('\\\\', '/'))
# Finally, replace all non alphanumeric, underscore or periods with underscore
@filename = just_filename.gsub(/[^\w\.\-]/,'_')
end
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require "digest/md5"
class Attachment < ActiveRecord::Base
belongs_to :container, :polymorphic => true
belongs_to :author, :class_name => "User", :foreign_key => "author_id"
validates_presence_of :container, :filename
cattr_accessor :storage_path
@@storage_path = "#{RAILS_ROOT}/files"
def validate
errors.add_to_base :too_long if self.filesize > Setting.attachment_max_size.to_i.kilobytes
end
def file=(incomming_file)
unless incomming_file.nil?
@temp_file = incomming_file
if @temp_file.size > 0
self.filename = sanitize_filename(@temp_file.original_filename)
self.disk_filename = DateTime.now.strftime("%y%m%d%H%M%S") + "_" + self.filename
self.content_type = @temp_file.content_type
self.filesize = @temp_file.size
end
end
end
def file
nil
end
# Copy temp file to its final location
def before_save
if @temp_file && (@temp_file.size > 0)
logger.debug("saving '#{self.diskfile}'")
File.open(diskfile, "wb") do |f|
f.write(@temp_file.read)
end
self.digest = Digest::MD5.hexdigest(File.read(diskfile))
end
end
# Deletes file on the disk
def after_destroy
if self.filename?
File.delete(diskfile) if File.exist?(diskfile)
end
end
# Returns file's location on disk
def diskfile
"#{@@storage_path}/#{self.disk_filename}"
end
def increment_download
increment!(:downloads)
end
# returns last created projects
def self.most_downloaded
find(:all, :limit => 5, :order => "downloads DESC")
end
private
def sanitize_filename(value)
# get only the filename, not the whole path
just_filename = value.gsub(/^.*(\\|\/)/, '')
# NOTE: File.basename doesn't work right with Windows paths on Unix
# INCORRECT: just_filename = File.basename(value.gsub('\\\\', '/'))
# Finally, replace all non alphanumeric, underscore or periods with underscore
@filename = just_filename.gsub(/[^\w\.\-]/,'_')
end
end

View File

@@ -1,79 +1,79 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'net/ldap'
require 'iconv'
class AuthSourceLdap < AuthSource
validates_presence_of :host, :port, :attr_login
def after_initialize
self.port = 389 if self.port == 0
end
def authenticate(login, password)
attrs = []
# get user's DN
ldap_con = initialize_ldap_con(self.account, self.account_password)
login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
dn = String.new
ldap_con.search( :base => self.base_dn,
:filter => object_filter & login_filter,
:attributes=> ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]) do |entry|
dn = entry.dn
attrs = [:firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
:lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
:mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
:auth_source_id => self.id ]
end
return nil if dn.empty?
logger.debug "DN found for #{login}: #{dn}" if logger && logger.debug?
# authenticate user
ldap_con = initialize_ldap_con(dn, password)
return nil unless ldap_con.bind
# return user's attributes
logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
attrs
rescue Net::LDAP::LdapError => text
raise "LdapError: " + text
end
# test the connection to the LDAP
def test_connection
ldap_con = initialize_ldap_con(self.account, self.account_password)
ldap_con.open { }
rescue Net::LDAP::LdapError => text
raise "LdapError: " + text
end
def auth_method_name
"LDAP"
end
private
def initialize_ldap_con(ldap_user, ldap_password)
Net::LDAP.new( {:host => self.host,
:port => self.port,
:auth => { :method => :simple, :username => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_user), :password => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_password) }}
)
end
def self.get_attr(entry, attr_name)
entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'net/ldap'
require 'iconv'
class AuthSourceLdap < AuthSource
validates_presence_of :host, :port, :attr_login
def after_initialize
self.port = 389 if self.port == 0
end
def authenticate(login, password)
attrs = []
# get user's DN
ldap_con = initialize_ldap_con(self.account, self.account_password)
login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
dn = String.new
ldap_con.search( :base => self.base_dn,
:filter => object_filter & login_filter,
:attributes=> ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]) do |entry|
dn = entry.dn
attrs = [:firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
:lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
:mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
:auth_source_id => self.id ]
end
return nil if dn.empty?
logger.debug "DN found for #{login}: #{dn}" if logger && logger.debug?
# authenticate user
ldap_con = initialize_ldap_con(dn, password)
return nil unless ldap_con.bind
# return user's attributes
logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
attrs
rescue Net::LDAP::LdapError => text
raise "LdapError: " + text
end
# test the connection to the LDAP
def test_connection
ldap_con = initialize_ldap_con(self.account, self.account_password)
ldap_con.open { }
rescue Net::LDAP::LdapError => text
raise "LdapError: " + text
end
def auth_method_name
"LDAP"
end
private
def initialize_ldap_con(ldap_user, ldap_password)
Net::LDAP.new( {:host => self.host,
:port => self.port,
:auth => { :method => :simple, :username => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_user), :password => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_password) }}
)
end
def self.get_attr(entry, attr_name)
entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
end
end

22
app/models/change.rb Normal file
View File

@@ -0,0 +1,22 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Change < ActiveRecord::Base
belongs_to :changeset
validates_presence_of :changeset_id, :action, :path
end

30
app/models/changeset.rb Normal file
View File

@@ -0,0 +1,30 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Changeset < ActiveRecord::Base
belongs_to :repository
has_many :changes, :dependent => :delete_all
validates_presence_of :repository_id, :revision, :committed_on, :commit_date
validates_numericality_of :revision, :only_integer => true
validates_uniqueness_of :revision, :scope => :repository_id
def committed_on=(date)
self.commit_date = date
super
end
end

View File

@@ -1,28 +1,23 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class News < ActiveRecord::Base
belongs_to :project
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
validates_presence_of :title, :description
# returns last created news
def self.latest
find(:all, :limit => 5, :include => [ :author, :project ], :order => "news.created_on DESC")
end
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Comment < ActiveRecord::Base
belongs_to :commented, :polymorphic => true, :counter_cache => true
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
validates_presence_of :commented, :author, :comment
end

View File

@@ -1,42 +1,60 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomField < ActiveRecord::Base
has_many :custom_values, :dependent => true
FIELD_FORMATS = { "list" => :label_list,
"date" => :label_date,
"bool" => :label_boolean,
"int" => :label_integer,
"string" => :label_string,
"text" => :label_text
}.freeze
validates_presence_of :name, :field_format
validates_uniqueness_of :name
validates_inclusion_of :field_format, :in => FIELD_FORMATS.keys
validates_presence_of :possible_values, :if => Proc.new { |field| field.field_format == "list" }
# to move in project_custom_field
def self.for_all
find(:all, :conditions => ["is_for_all=?", true])
end
def type_name
nil
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomField < ActiveRecord::Base
has_many :custom_values, :dependent => :delete_all
serialize :possible_values
FIELD_FORMATS = { "string" => { :name => :label_string, :order => 1 },
"text" => { :name => :label_text, :order => 2 },
"int" => { :name => :label_integer, :order => 3 },
"list" => { :name => :label_list, :order => 4 },
"date" => { :name => :label_date, :order => 5 },
"bool" => { :name => :label_boolean, :order => 6 }
}.freeze
validates_presence_of :name, :field_format
validates_uniqueness_of :name
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
validates_inclusion_of :field_format, :in => FIELD_FORMATS.keys
def initialize(attributes = nil)
super
self.possible_values ||= []
end
end
def before_validation
# remove empty values
self.possible_values = self.possible_values.collect{|v| v unless v.empty?}.compact
end
def validate
if self.field_format == "list"
errors.add(:possible_values, :activerecord_error_blank) if self.possible_values.nil? || self.possible_values.empty?
errors.add(:possible_values, :activerecord_error_invalid) unless self.possible_values.is_a? Array
end
end
# to move in project_custom_field
def self.for_all
find(:all, :conditions => ["is_for_all=?", true])
end
def type_name
nil
end
end

View File

@@ -1,38 +1,38 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomValue < ActiveRecord::Base
belongs_to :custom_field
belongs_to :customized, :polymorphic => true
protected
def validate
errors.add(:value, :activerecord_error_blank) and return if custom_field.is_required? and value.empty?
errors.add(:value, :activerecord_error_invalid) unless custom_field.regexp.empty? or value =~ Regexp.new(custom_field.regexp)
errors.add(:value, :activerecord_error_too_short) if custom_field.min_length > 0 and value.length < custom_field.min_length and value.length > 0
errors.add(:value, :activerecord_error_too_long) if custom_field.max_length > 0 and value.length > custom_field.max_length
case custom_field.field_format
when "int"
errors.add(:value, :activerecord_error_not_a_number) unless value =~ /^[0-9]*$/
when "date"
errors.add(:value, :activerecord_error_invalid) unless value =~ /^(\d+)\/(\d+)\/(\d+)$/ or value.empty?
when "list"
errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.split('|').include? value or value.empty?
end
end
end
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomValue < ActiveRecord::Base
belongs_to :custom_field
belongs_to :customized, :polymorphic => true
protected
def validate
errors.add(:value, :activerecord_error_blank) and return if custom_field.is_required? and value.empty?
errors.add(:value, :activerecord_error_invalid) unless custom_field.regexp.empty? or value =~ Regexp.new(custom_field.regexp)
errors.add(:value, :activerecord_error_too_short) if custom_field.min_length > 0 and value.length < custom_field.min_length and value.length > 0
errors.add(:value, :activerecord_error_too_long) if custom_field.max_length > 0 and value.length > custom_field.max_length
case custom_field.field_format
when "int"
errors.add(:value, :activerecord_error_not_a_number) unless value =~ /^[0-9]*$/
when "date"
errors.add(:value, :activerecord_error_not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ or value.empty?
when "list"
errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.include? value or value.empty?
end
end
end

View File

@@ -1,24 +1,24 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Document < ActiveRecord::Base
belongs_to :project
belongs_to :category, :class_name => "Enumeration", :foreign_key => "category_id"
has_many :attachments, :as => :container, :dependent => true
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Document < ActiveRecord::Base
belongs_to :project
belongs_to :category, :class_name => "Enumeration", :foreign_key => "category_id"
has_many :attachments, :as => :container, :dependent => :destroy
validates_presence_of :project, :title, :category
end

View File

@@ -1,42 +1,50 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Enumeration < ActiveRecord::Base
before_destroy :check_integrity
validates_presence_of :opt, :name
validates_uniqueness_of :name, :scope => [:opt]
OPTIONS = {
"IPRI" => :enumeration_issue_priorities,
"DCAT" => :enumeration_doc_categories
}.freeze
def self.get_values(option)
find(:all, :conditions => ['opt=?', option])
end
private
def check_integrity
case self.opt
when "IPRI"
raise "Can't delete enumeration" if Issue.find(:first, :conditions => ["priority_id=?", self.id])
when "DCAT"
raise "Can't delete enumeration" if Document.find(:first, :conditions => ["category_id=?", self.id])
end
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Enumeration < ActiveRecord::Base
before_destroy :check_integrity
validates_presence_of :opt, :name
validates_uniqueness_of :name, :scope => [:opt]
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
OPTIONS = {
"IPRI" => :enumeration_issue_priorities,
"DCAT" => :enumeration_doc_categories,
"ACTI" => :enumeration_activities
}.freeze
def self.get_values(option)
find(:all, :conditions => ['opt=?', option])
end
def option_name
OPTIONS[self.opt]
end
private
def check_integrity
case self.opt
when "IPRI"
raise "Can't delete enumeration" if Issue.find(:first, :conditions => ["priority_id=?", self.id])
when "DCAT"
raise "Can't delete enumeration" if Document.find(:first, :conditions => ["category_id=?", self.id])
when "ACTI"
raise "Can't delete enumeration" if TimeEntry.find(:first, :conditions => ["activity_id=?", self.id])
end
end
end

106
app/models/issue.rb Normal file
View File

@@ -0,0 +1,106 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Issue < ActiveRecord::Base
belongs_to :project
belongs_to :tracker
belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id'
belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id'
belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
has_many :journals, :as => :journalized, :dependent => :destroy
has_many :attachments, :as => :container, :dependent => :destroy
has_many :time_entries
has_many :custom_values, :dependent => :delete_all, :as => :customized
has_many :custom_fields, :through => :custom_values
validates_presence_of :subject, :description, :priority, :tracker, :author, :status
validates_inclusion_of :done_ratio, :in => 0..100
validates_associated :custom_values, :on => :update
# set default status for new issues
def before_validation
self.status = IssueStatus.default if status.nil?
end
def validate
if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
errors.add :due_date, :activerecord_error_not_a_date
end
if self.due_date and self.start_date and self.due_date < self.start_date
errors.add :due_date, :activerecord_error_greater_than_start_date
end
end
#def before_create
# build_history
#end
def before_save
if @current_journal
# attributes changes
(Issue.column_names - %w(id description)).each {|c|
@current_journal.details << JournalDetail.new(:property => 'attr',
:prop_key => c,
:old_value => @issue_before_change.send(c),
:value => send(c)) unless send(c)==@issue_before_change.send(c)
}
# custom fields changes
custom_values.each {|c|
@current_journal.details << JournalDetail.new(:property => 'cf',
:prop_key => c.custom_field_id,
:old_value => @custom_values_before_change[c.custom_field_id],
:value => c.value) unless @custom_values_before_change[c.custom_field_id]==c.value
}
@current_journal.save unless @current_journal.details.empty? and @current_journal.notes.empty?
end
end
def long_id
"%05d" % self.id
end
def custom_value_for(custom_field)
self.custom_values.each {|v| return v if v.custom_field_id == custom_field.id }
return nil
end
def init_journal(user, notes = "")
@current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes)
@issue_before_change = self.clone
@custom_values_before_change = {}
self.custom_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value }
@current_journal
end
def spent_hours
@spent_hours ||= time_entries.sum(:hours) || 0
end
private
# Creates an history for the issue
#def build_history
# @history = self.histories.build
# @history.status = self.status
# @history.author = self.author
#end
end

View File

@@ -1,29 +1,29 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCategory < ActiveRecord::Base
before_destroy :check_integrity
belongs_to :project
validates_presence_of :name
validates_uniqueness_of :name, :scope => [:project_id]
private
def check_integrity
raise "Can't delete category" if Issue.find(:first, :conditions => ["category_id=?", self.id])
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCategory < ActiveRecord::Base
before_destroy :check_integrity
belongs_to :project
validates_presence_of :name
validates_uniqueness_of :name, :scope => [:project_id]
private
def check_integrity
raise "Can't delete category" if Issue.find(:first, :conditions => ["category_id=?", self.id])
end
end

View File

@@ -1,27 +1,27 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCustomField < CustomField
has_and_belongs_to_many :projects, :join_table => "custom_fields_projects", :foreign_key => "custom_field_id"
has_and_belongs_to_many :trackers, :join_table => "custom_fields_trackers", :foreign_key => "custom_field_id"
has_many :issues, :through => :issue_custom_values
def type_name
:label_issue_plural
end
end
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCustomField < CustomField
has_and_belongs_to_many :projects, :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :foreign_key => "custom_field_id"
has_and_belongs_to_many :trackers, :join_table => "#{table_name_prefix}custom_fields_trackers#{table_name_suffix}", :foreign_key => "custom_field_id"
has_many :issues, :through => :issue_custom_values
def type_name
:label_issue_plural
end
end

View File

@@ -1,23 +1,24 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueHistory < ActiveRecord::Base
belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
validates_presence_of :status
belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
belongs_to :issue
validates_presence_of :status
end

View File

@@ -1,45 +1,60 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueStatus < ActiveRecord::Base
before_destroy :check_integrity
has_many :workflows, :foreign_key => "old_status_id"
validates_presence_of :name
validates_uniqueness_of :name
validates_length_of :html_color, :is=>6
validates_format_of :html_color, :with => /^[a-f0-9]*$/i
# Returns the default status for new issues
def self.default
find(:first, :conditions =>["is_default=?", true])
end
# Returns an array of all statuses the given role can switch to
def new_statuses_allowed_to(role, tracker)
statuses = []
for workflow in self.workflows
statuses << workflow.new_status if workflow.role_id == role.id and workflow.tracker_id == tracker.id
end unless role.nil? or tracker.nil?
statuses
end
private
def check_integrity
raise "Can't delete status" if Issue.find(:first, :conditions => ["status_id=?", self.id]) or IssueHistory.find(:first, :conditions => ["status_id=?", self.id])
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueStatus < ActiveRecord::Base
before_destroy :check_integrity
has_many :workflows, :foreign_key => "old_status_id"
acts_as_list
validates_presence_of :name
validates_uniqueness_of :name
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
validates_length_of :html_color, :is => 6
validates_format_of :html_color, :with => /^[a-f0-9]*$/i
def before_save
IssueStatus.update_all "is_default=#{connection.quoted_false}" if self.is_default?
end
# Returns the default status for new issues
def self.default
find(:first, :conditions =>["is_default=?", true])
end
# Returns an array of all statuses the given role can switch to
# Uses association cache when called more than one time
def new_statuses_allowed_to(role, tracker)
new_statuses = [self]
new_statuses += workflows.select {|w| w.role_id == role.id && w.tracker_id == tracker.id}.collect{|w| w.new_status} if role && tracker
new_statuses.sort{|x, y| x.position <=> y.position }
end
# Same thing as above but uses a database query
# More efficient than the previous method if called just once
def find_new_statuses_allowed_to(role, tracker)
new_statuses = [self]
new_statuses += workflows.find(:all,
:include => :new_status,
:conditions => ["role_id=? and tracker_id=?", role.id, tracker.id]).collect{ |w| w.new_status } if role && tracker
new_statuses.sort{|x, y| x.position <=> y.position }
end
private
def check_integrity
raise "Can't delete status" if Issue.find(:first, :conditions => ["status_id=?", self.id])
end
end

26
app/models/journal.rb Normal file
View File

@@ -0,0 +1,26 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Journal < ActiveRecord::Base
belongs_to :journalized, :polymorphic => true
# added as a quick fix to allow eager loading of the polymorphic association
# since always associated to an issue, for now
belongs_to :issue, :foreign_key => :journalized_id
belongs_to :user
has_many :details, :class_name => "JournalDetail", :dependent => :delete_all
end

View File

@@ -0,0 +1,20 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class JournalDetail < ActiveRecord::Base
belongs_to :journal
end

88
app/models/mailer.rb Normal file
View File

@@ -0,0 +1,88 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Mailer < ActionMailer::Base
helper IssuesHelper
def issue_add(issue)
set_language_if_valid(Setting.default_language)
# Sends to all project members
@recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification }.compact
@from = Setting.mail_from
@subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] #{issue.status.name} - #{issue.subject}"
@body['issue'] = issue
end
def issue_edit(journal)
set_language_if_valid(Setting.default_language)
# Sends to all project members
issue = journal.journalized
@recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification }.compact
@from = Setting.mail_from
@subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] #{issue.status.name} - #{issue.subject}"
@body['issue'] = issue
@body['journal']= journal
end
def document_add(document)
set_language_if_valid(Setting.default_language)
@recipients = document.project.users.collect { |u| u.mail if u.mail_notification }.compact
@from = Setting.mail_from
@subject = "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
@body['document'] = document
end
def attachments_add(attachments)
set_language_if_valid(Setting.default_language)
container = attachments.first.container
url = "http://#{Setting.host_name}/"
added_to = ""
case container.class.to_s
when 'Version'
url << "projects/list_files/#{container.project_id}"
added_to = "#{l(:label_version)}: #{container.name}"
when 'Document'
url << "documents/show/#{container.id}"
added_to = "#{l(:label_document)}: #{container.title}"
when 'Issue'
url << "issues/show/#{container.id}"
added_to = "#{container.tracker.name} ##{container.id}: #{container.subject}"
end
@recipients = container.project.users.collect { |u| u.mail if u.mail_notification }.compact
@from = Setting.mail_from
@subject = "[#{container.project.name}] #{l(:label_attachment_new)}"
@body['attachments'] = attachments
@body['url'] = url
@body['added_to'] = added_to
end
def lost_password(token)
set_language_if_valid(token.user.language)
@recipients = token.user.mail
@from = Setting.mail_from
@subject = l(:mail_subject_lost_password)
@body['token'] = token
end
def register(token)
set_language_if_valid(token.user.language)
@recipients = token.user.mail
@from = Setting.mail_from
@subject = l(:mail_subject_register)
@body['token'] = token
end
end

View File

@@ -1,29 +1,29 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Member < ActiveRecord::Base
belongs_to :user
belongs_to :role
belongs_to :project
validates_presence_of :role, :user, :project
validates_uniqueness_of :user_id, :scope => :project_id
def name
self.user.display_name
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Member < ActiveRecord::Base
belongs_to :user
belongs_to :role
belongs_to :project
validates_presence_of :role, :user, :project
validates_uniqueness_of :user_id, :scope => :project_id
def name
self.user.display_name
end
end

29
app/models/news.rb Normal file
View File

@@ -0,0 +1,29 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class News < ActiveRecord::Base
belongs_to :project
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
validates_presence_of :title, :description
# returns latest news for projects visible by user
def self.latest(user=nil, count=5)
find(:all, :limit => count, :conditions => Project.visible_by(user), :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
end
end

View File

@@ -1,63 +1,66 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Permission < ActiveRecord::Base
has_and_belongs_to_many :roles
validates_presence_of :controller, :action, :description
GROUPS = {
100 => :label_project,
200 => :label_member_plural,
300 => :label_version_plural,
400 => :label_issue_category_plural,
1000 => :label_issue_plural,
1100 => :label_news_plural,
1200 => :label_document_plural,
1300 => :label_attachment_plural,
}.freeze
@@cached_perms_for_public = nil
@@cached_perms_for_roles = nil
def name
self.controller + "/" + self.action
end
def group_id
(self.sort / 100)*100
end
def self.allowed_to_public(action)
@@cached_perms_for_public ||= find(:all, :conditions => ["is_public=?", true]).collect {|p| "#{p.controller}/#{p.action}"}
@@cached_perms_for_public.include? action
end
def self.allowed_to_role(action, role)
@@cached_perms_for_roles ||=
begin
perms = {}
find(:all, :include => :roles).each {|p| perms.store "#{p.controller}/#{p.action}", p.roles.collect {|r| r.id } }
perms
end
@@cached_perms_for_roles[action] and @@cached_perms_for_roles[action].include? role
end
def self.allowed_to_role_expired
@@cached_perms_for_roles = nil
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Permission < ActiveRecord::Base
has_and_belongs_to_many :roles
validates_presence_of :controller, :action, :description
GROUPS = {
100 => :label_project,
200 => :label_member_plural,
300 => :label_version_plural,
400 => :label_issue_category_plural,
600 => :label_query_plural,
1000 => :label_issue_plural,
1100 => :label_news_plural,
1200 => :label_document_plural,
1300 => :label_attachment_plural,
1400 => :label_repository,
1500 => :label_time_tracking
}.freeze
@@cached_perms_for_public = nil
@@cached_perms_for_roles = nil
def name
self.controller + "/" + self.action
end
def group_id
(self.sort / 100)*100
end
def self.allowed_to_public(action)
@@cached_perms_for_public ||= find(:all, :conditions => ["is_public=?", true]).collect {|p| "#{p.controller}/#{p.action}"}
@@cached_perms_for_public.include? action
end
def self.allowed_to_role(action, role)
@@cached_perms_for_roles ||=
begin
perms = {}
find(:all, :include => :roles).each {|p| perms.store "#{p.controller}/#{p.action}", p.roles.collect {|r| r.id } }
perms
end
allowed_to_public(action) or (role && @@cached_perms_for_roles[action] && @@cached_perms_for_roles[action].include?(role.id))
end
def self.allowed_to_role_expired
@@cached_perms_for_roles = nil
end
end

94
app/models/project.rb Normal file
View File

@@ -0,0 +1,94 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Project < ActiveRecord::Base
has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
has_many :members, :dependent => :delete_all, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}"
has_many :users, :through => :members
has_many :custom_values, :dependent => :delete_all, :as => :customized
has_many :issues, :dependent => :destroy, :order => "#{Issue.table_name}.created_on DESC", :include => [:status, :tracker]
has_many :time_entries, :dependent => :delete_all
has_many :queries, :dependent => :delete_all
has_many :documents, :dependent => :destroy
has_many :news, :dependent => :delete_all, :include => :author
has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
has_one :repository, :dependent => :destroy
has_one :wiki, :dependent => :destroy
has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :association_foreign_key => 'custom_field_id'
acts_as_tree :order => "name", :counter_cache => true
validates_presence_of :name, :description, :identifier
validates_uniqueness_of :name, :identifier
validates_associated :custom_values, :on => :update
validates_associated :repository, :wiki
validates_length_of :name, :maximum => 30
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
validates_length_of :description, :maximum => 255
validates_length_of :identifier, :in => 3..12
validates_format_of :identifier, :with => /^[a-z0-9\-]*$/
def identifier=(identifier)
super unless identifier_frozen?
end
def identifier_frozen?
errors[:identifier].nil? && !(new_record? || identifier.blank?)
end
def issues_with_subprojects(include_subprojects=false)
conditions = nil
if include_subprojects && children.size > 0
ids = [id] + children.collect {|c| c.id}
conditions = ["#{Issue.table_name}.project_id IN (#{ids.join(',')})"]
else
conditions = ["#{Issue.table_name}.project_id = ?", id]
end
Issue.with_scope :find => { :conditions => conditions } do
yield
end
end
# returns latest created projects
# non public projects will be returned only if user is a member of those
def self.latest(user=nil, count=5)
find(:all, :limit => count, :conditions => visible_by(user), :order => "created_on DESC")
end
def self.visible_by(user=nil)
if user && !user.memberships.empty?
return ["#{Project.table_name}.is_public = ? or #{Project.table_name}.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')})", true]
else
return ["#{Project.table_name}.is_public = ?", true]
end
end
# Returns an array of all custom fields enabled for project issues
# (explictly associated custom fields and custom fields enabled for all projects)
def custom_fields_for_issues(tracker)
all_custom_fields.select {|c| tracker.custom_fields.include? c }
end
def all_custom_fields
@all_custom_fields ||= (IssueCustomField.for_all + custom_fields).uniq
end
protected
def validate
errors.add(parent_id, " must be a root project") if parent and parent.parent
errors.add_to_base("A project with subprojects can't be a subproject") if parent and children.size > 0
end
end

View File

@@ -1,22 +1,22 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ProjectCustomField < CustomField
def type_name
:label_project_plural
end
end
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ProjectCustomField < CustomField
def type_name
:label_project_plural
end
end

182
app/models/query.rb Normal file
View File

@@ -0,0 +1,182 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Query < ActiveRecord::Base
belongs_to :project
belongs_to :user
serialize :filters
attr_protected :project, :user
validates_presence_of :name, :on => :save
@@operators = { "=" => :label_equals,
"!" => :label_not_equals,
"o" => :label_open_issues,
"c" => :label_closed_issues,
"!*" => :label_none,
"*" => :label_all,
"<t+" => :label_in_less_than,
">t+" => :label_in_more_than,
"t+" => :label_in,
"t" => :label_today,
">t-" => :label_less_than_ago,
"<t-" => :label_more_than_ago,
"t-" => :label_ago,
"~" => :label_contains,
"!~" => :label_not_contains }
cattr_reader :operators
@@operators_by_filter_type = { :list => [ "=", "!" ],
:list_status => [ "o", "=", "!", "c", "*" ],
:list_optional => [ "=", "!", "!*", "*" ],
:list_one_or_more => [ "*", "=" ],
:date => [ "<t+", ">t+", "t+", "t", ">t-", "<t-", "t-" ],
:date_past => [ ">t-", "<t-", "t-", "t" ],
:text => [ "~", "!~" ] }
cattr_reader :operators_by_filter_type
def initialize(attributes = nil)
super attributes
self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
self.is_public = true
end
def validate
filters.each_key do |field|
errors.add field.gsub(/\_id$/, ""), :activerecord_error_blank unless
# filter requires one or more values
(values_for(field) and !values_for(field).first.empty?) or
# filter doesn't require any value
["o", "c", "!*", "*", "t"].include? operator_for(field)
end if filters
end
def available_filters
return @available_filters if @available_filters
@available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
"tracker_id" => { :type => :list, :order => 2, :values => Tracker.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
"priority_id" => { :type => :list, :order => 3, :values => Enumeration.find(:all, :conditions => ['opt=?','IPRI']).collect{|s| [s.name, s.id.to_s] } },
"subject" => { :type => :text, :order => 8 },
"created_on" => { :type => :date_past, :order => 9 },
"updated_on" => { :type => :date_past, :order => 10 },
"start_date" => { :type => :date, :order => 11 },
"due_date" => { :type => :date, :order => 12 } }
unless project.nil?
# project specific filters
@available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => @project.users.collect{|s| [s.name, s.id.to_s] } }
@available_filters["author_id"] = { :type => :list, :order => 5, :values => @project.users.collect{|s| [s.name, s.id.to_s] } }
@available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } }
@available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.versions.collect{|s| [s.name, s.id.to_s] } }
unless @project.children.empty?
@available_filters["subproject_id"] = { :type => :list_one_or_more, :order => 13, :values => @project.children.collect{|s| [s.name, s.id.to_s] } }
end
# remove category filter if no category defined
@available_filters.delete "category_id" if @available_filters["category_id"][:values].empty?
end
@available_filters
end
def add_filter(field, operator, values)
# values must be an array
return unless values and values.is_a? Array # and !values.first.empty?
# check if field is defined as an available filter
if available_filters.has_key? field
filter_options = available_filters[field]
# check if operator is allowed for that filter
#if @@operators_by_filter_type[filter_options[:type]].include? operator
# allowed_values = values & ([""] + (filter_options[:values] || []).collect {|val| val[1]})
# filters[field] = {:operator => operator, :values => allowed_values } if (allowed_values.first and !allowed_values.first.empty?) or ["o", "c", "!*", "*", "t"].include? operator
#end
filters[field] = {:operator => operator, :values => values }
end
end
def add_short_filter(field, expression)
return unless expression
parms = expression.scan(/^(o|c|\!|\*)?(.*)$/).first
add_filter field, (parms[0] || "="), [parms[1] || ""]
end
def has_filter?(field)
filters and filters[field]
end
def operator_for(field)
has_filter?(field) ? filters[field][:operator] : nil
end
def values_for(field)
has_filter?(field) ? filters[field][:values] : nil
end
def statement
sql = "1=1"
if has_filter?("subproject_id")
subproject_ids = []
if operator_for("subproject_id") == "="
subproject_ids = values_for("subproject_id").each(&:to_i)
else
subproject_ids = project.children.collect{|p| p.id}
end
sql << " AND #{Issue.table_name}.project_id IN (%d,%s)" % [project.id, subproject_ids.join(",")] if project
else
sql << " AND #{Issue.table_name}.project_id=%d" % project.id if project
end
filters.each_key do |field|
next if field == "subproject_id"
v = values_for field
next unless v and !v.empty?
sql = sql + " AND " unless sql.empty?
case operator_for field
when "="
sql = sql + "#{Issue.table_name}.#{field} IN (" + v.each(&:to_i).join(",") + ")"
when "!"
sql = sql + "#{Issue.table_name}.#{field} NOT IN (" + v.each(&:to_i).join(",") + ")"
when "!*"
sql = sql + "#{Issue.table_name}.#{field} IS NULL"
when "*"
sql = sql + "#{Issue.table_name}.#{field} IS NOT NULL"
when "o"
sql = sql + "#{IssueStatus.table_name}.is_closed=#{connection.quoted_false}" if field == "status_id"
when "c"
sql = sql + "#{IssueStatus.table_name}.is_closed=#{connection.quoted_true}" if field == "status_id"
when ">t-"
sql = sql + "#{Issue.table_name}.#{field} >= '%s'" % connection.quoted_date(Date.today - v.first.to_i)
when "<t-"
sql = sql + "#{Issue.table_name}.#{field} <= '" + (Date.today - v.first.to_i).strftime("%Y-%m-%d") + "'"
when "t-"
sql = sql + "#{Issue.table_name}.#{field} = '" + (Date.today - v.first.to_i).strftime("%Y-%m-%d") + "'"
when ">t+"
sql = sql + "#{Issue.table_name}.#{field} >= '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'"
when "<t+"
sql = sql + "#{Issue.table_name}.#{field} <= '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'"
when "t+"
sql = sql + "#{Issue.table_name}.#{field} = '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'"
when "t"
sql = sql + "#{Issue.table_name}.#{field} = '%s'" % connection.quoted_date(Date.today)
when "~"
sql = sql + "#{Issue.table_name}.#{field} LIKE '%#{connection.quote_string(v.first)}%'"
when "!~"
sql = sql + "#{Issue.table_name}.#{field} NOT LIKE '%#{connection.quote_string(v.first)}%'"
end
end if filters and valid?
sql
end
end

88
app/models/repository.rb Normal file
View File

@@ -0,0 +1,88 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Repository < ActiveRecord::Base
belongs_to :project
has_many :changesets, :dependent => :destroy, :order => 'revision DESC'
has_many :changes, :through => :changesets
has_one :latest_changeset, :class_name => 'Changeset', :foreign_key => :repository_id, :order => 'revision DESC'
attr_protected :root_url
validates_presence_of :url
validates_format_of :url, :with => /^(http|https|svn|file):\/\/.+/i
def scm
@scm ||= SvnRepos::Base.new url, root_url, login, password
update_attribute(:root_url, @scm.root_url) if root_url.blank?
@scm
end
def url=(str)
super if root_url.blank?
end
def changesets_with_path(path="")
path = "/#{path}%"
path = url.gsub(/^#{root_url}/, '') + path if root_url && root_url != url
path.squeeze!("/")
Changeset.with_scope(:find => { :include => :changes, :conditions => ["#{Change.table_name}.path LIKE ?", path] }) do
yield
end
end
def fetch_changesets
scm_info = scm.info
if scm_info
lastrev_identifier = scm_info.lastrev.identifier.to_i
if latest_changeset.nil? || latest_changeset.revision < lastrev_identifier
logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
identifier_from = latest_changeset ? latest_changeset.revision + 1 : 1
while (identifier_from <= lastrev_identifier)
# loads changesets by batches of 200
identifier_to = [identifier_from + 199, lastrev_identifier].min
revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
transaction do
revisions.reverse_each do |revision|
changeset = Changeset.create(:repository => self,
:revision => revision.identifier,
:committer => revision.author,
:committed_on => revision.time,
:comment => revision.message)
revision.paths.each do |change|
Change.create(:changeset => changeset,
:action => change[:action],
:path => change[:path],
:from_path => change[:from_path],
:from_revision => change[:from_revision])
end
end
end unless revisions.nil?
identifier_from = identifier_to + 1
end
end
end
end
# fetch new changesets for all repositories
# can be called periodically by an external script
# eg. ruby script/runner "Repository.fetch_changesets"
def self.fetch_changesets
find(:all).each(&:fetch_changesets)
end
end

View File

@@ -1,31 +1,37 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Role < ActiveRecord::Base
before_destroy :check_integrity
has_and_belongs_to_many :permissions
has_many :workflows, :dependent => true
has_many :members
validates_presence_of :name
validates_uniqueness_of :name
private
def check_integrity
raise "Can't delete role" if Member.find(:first, :conditions =>["role_id=?", self.id])
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Role < ActiveRecord::Base
before_destroy :check_integrity
has_and_belongs_to_many :permissions
has_many :workflows, :dependent => :delete_all
has_many :members
acts_as_list
validates_presence_of :name
validates_uniqueness_of :name
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
def <=>(role)
position <=> role.position
end
private
def check_integrity
raise "Can't delete role" if Member.find(:first, :conditions =>["role_id=?", self.id])
end
end

61
app/models/setting.rb Normal file
View File

@@ -0,0 +1,61 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Setting < ActiveRecord::Base
cattr_accessor :available_settings
@@available_settings = YAML::load(File.open("#{RAILS_ROOT}/config/settings.yml"))
validates_uniqueness_of :name
validates_inclusion_of :name, :in => @@available_settings.keys
validates_numericality_of :value, :only_integer => true, :if => Proc.new { |setting| @@available_settings[setting.name]['format'] == 'int' }
def self.get(name)
name = name.to_s
setting = find_by_name(name)
setting ||= new(:name => name, :value => @@available_settings[name]['default']) if @@available_settings.has_key? name
setting
end
def self.[](name)
get(name).value
end
def self.[]=(name, value)
setting = get(name)
setting.value = (value ? value.to_s : "")
setting.save
setting.value
end
@@available_settings.each do |name, params|
src = <<-END_SRC
def self.#{name}
self[:#{name}]
end
def self.#{name}?
self[:#{name}].to_s == "1"
end
def self.#{name}=(value)
self[:#{name}] = value
end
END_SRC
class_eval src, __FILE__, __LINE__
end
end

431
app/models/svn_repos.rb Normal file
View File

@@ -0,0 +1,431 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'rexml/document'
require 'cgi'
module SvnRepos
class CommandFailed < StandardError #:nodoc:
end
class Base
def initialize(url, root_url=nil, login=nil, password=nil)
@url = url
@login = login if login && !login.empty?
@password = (password || "") if @login
@root_url = root_url.blank? ? retrieve_root_url : root_url
end
def root_url
@root_url
end
def url
@url
end
# get info about the svn repository
def info
cmd = "svn info --xml #{target('')}"
cmd << " --username #{@login} --password #{@password}" if @login
info = nil
shellout(cmd) do |io|
begin
doc = REXML::Document.new(io)
#root_url = doc.elements["info/entry/repository/root"].text
info = Info.new({:root_url => doc.elements["info/entry/repository/root"].text,
:lastrev => Revision.new({
:identifier => doc.elements["info/entry/commit"].attributes['revision'],
:time => Time.parse(doc.elements["info/entry/commit/date"].text),
:author => (doc.elements["info/entry/commit/author"] ? doc.elements["info/entry/commit/author"].text : "")
})
})
rescue
end
end
return nil if $? && $?.exitstatus != 0
info
rescue Errno::ENOENT => e
return nil
end
# Returns the entry identified by path and revision identifier
# or nil if entry doesn't exist in the repository
def entry(path=nil, identifier=nil)
e = entries(path, identifier)
e ? e.first : nil
end
# Returns an Entries collection
# or nil if the given path doesn't exist in the repository
def entries(path=nil, identifier=nil)
path ||= ''
identifier = 'HEAD' unless identifier and identifier > 0
entries = Entries.new
cmd = "svn list --xml #{target(path)}@#{identifier}"
cmd << " --username #{@login} --password #{@password}" if @login
shellout(cmd) do |io|
begin
doc = REXML::Document.new(io)
doc.elements.each("lists/list/entry") do |entry|
entries << Entry.new({:name => entry.elements['name'].text,
:path => ((path.empty? ? "" : "#{path}/") + entry.elements['name'].text),
:kind => entry.attributes['kind'],
:size => (entry.elements['size'] and entry.elements['size'].text).to_i,
:lastrev => Revision.new({
:identifier => entry.elements['commit'].attributes['revision'],
:time => Time.parse(entry.elements['commit'].elements['date'].text),
:author => (entry.elements['commit'].elements['author'] ? entry.elements['commit'].elements['author'].text : "")
})
})
end
rescue
end
end
return nil if $? && $?.exitstatus != 0
entries.sort_by_name
rescue Errno::ENOENT => e
raise CommandFailed
end
def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
path ||= ''
identifier_from = 'HEAD' unless identifier_from and identifier_from.to_i > 0
identifier_to = 1 unless identifier_to and identifier_to.to_i > 0
revisions = Revisions.new
cmd = "svn log --xml -r #{identifier_from}:#{identifier_to}"
cmd << " --username #{@login} --password #{@password}" if @login
cmd << " --verbose " if options[:with_paths]
cmd << target(path)
shellout(cmd) do |io|
begin
doc = REXML::Document.new(io)
doc.elements.each("log/logentry") do |logentry|
paths = []
logentry.elements.each("paths/path") do |path|
paths << {:action => path.attributes['action'],
:path => path.text,
:from_path => path.attributes['copyfrom-path'],
:from_revision => path.attributes['copyfrom-rev']
}
end
paths.sort! { |x,y| x[:path] <=> y[:path] }
revisions << Revision.new({:identifier => logentry.attributes['revision'],
:author => (logentry.elements['author'] ? logentry.elements['author'].text : ""),
:time => Time.parse(logentry.elements['date'].text),
:message => logentry.elements['msg'].text,
:paths => paths
})
end
rescue
end
end
return nil if $? && $?.exitstatus != 0
revisions
rescue Errno::ENOENT => e
raise CommandFailed
end
def diff(path, identifier_from, identifier_to=nil, type="inline")
path ||= ''
if identifier_to and identifier_to.to_i > 0
identifier_to = identifier_to.to_i
else
identifier_to = identifier_from.to_i - 1
end
cmd = "svn diff -r "
cmd << "#{identifier_to}:"
cmd << "#{identifier_from}"
cmd << "#{target(path)}@#{identifier_from}"
cmd << " --username #{@login} --password #{@password}" if @login
diff = []
shellout(cmd) do |io|
io.each_line do |line|
diff << line
end
end
return nil if $? && $?.exitstatus != 0
DiffTableList.new diff, type
rescue Errno::ENOENT => e
raise CommandFailed
end
def cat(path, identifier=nil)
identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
cmd = "svn cat #{target(path)}@#{identifier}"
cmd << " --username #{@login} --password #{@password}" if @login
cat = nil
shellout(cmd) do |io|
cat = io.read
end
return nil if $? && $?.exitstatus != 0
cat
rescue Errno::ENOENT => e
raise CommandFailed
end
private
def retrieve_root_url
info = self.info
info ? info.root_url : nil
end
def target(path)
path ||= ""
base = path.match(/^\//) ? root_url : url
" \"" << "#{base}/#{path}".gsub(/["'?<>\*]/, '') << "\""
end
def logger
RAILS_DEFAULT_LOGGER
end
def shellout(cmd, &block)
logger.debug "Shelling out: #{cmd}" if logger && logger.debug?
IO.popen(cmd, "r+") do |io|
io.close_write
block.call(io) if block_given?
end
end
end
class Entries < Array
def sort_by_name
sort {|x,y|
if x.kind == y.kind
x.name <=> y.name
else
x.kind <=> y.kind
end
}
end
def revisions
revisions ||= Revisions.new(collect{|entry| entry.lastrev})
end
end
class Info
attr_accessor :root_url, :lastrev
def initialize(attributes={})
self.root_url = attributes[:root_url] if attributes[:root_url]
self.lastrev = attributes[:lastrev]
end
end
class Entry
attr_accessor :name, :path, :kind, :size, :lastrev
def initialize(attributes={})
self.name = attributes[:name] if attributes[:name]
self.path = attributes[:path] if attributes[:path]
self.kind = attributes[:kind] if attributes[:kind]
self.size = attributes[:size].to_i if attributes[:size]
self.lastrev = attributes[:lastrev]
end
def is_file?
'file' == self.kind
end
def is_dir?
'dir' == self.kind
end
end
class Revisions < Array
def latest
sort {|x,y| x.time <=> y.time}.last
end
end
class Revision
attr_accessor :identifier, :author, :time, :message, :paths
def initialize(attributes={})
self.identifier = attributes[:identifier]
self.author = attributes[:author]
self.time = attributes[:time]
self.message = attributes[:message] || ""
self.paths = attributes[:paths]
end
end
# A line of Diff
class Diff
attr_accessor :nb_line_left
attr_accessor :line_left
attr_accessor :nb_line_right
attr_accessor :line_right
attr_accessor :type_diff_right
attr_accessor :type_diff_left
def initialize ()
self.nb_line_left = ''
self.nb_line_right = ''
self.line_left = ''
self.line_right = ''
self.type_diff_right = ''
self.type_diff_left = ''
end
def inspect
puts '### Start Line Diff ###'
puts self.nb_line_left
puts self.line_left
puts self.nb_line_right
puts self.line_right
end
end
class DiffTableList < Array
def initialize (diff, type="inline")
diff_table = DiffTable.new type
diff.each do |line|
if line =~ /^Index: (.*)$/
self << diff_table if diff_table.length > 1
diff_table = DiffTable.new type
end
a = diff_table.add_line line
end
self << diff_table
end
end
# Class for create a Diff
class DiffTable < Hash
attr_reader :file_name, :line_num_l, :line_num_r
# Initialize with a Diff file and the type of Diff View
# The type view must be inline or sbs (side_by_side)
def initialize (type="inline")
@parsing = false
@nb_line = 1
@start = false
@before = 'same'
@second = true
@type = type
end
# Function for add a line of this Diff
def add_line(line)
unless @parsing
if line =~ /^Index: (.*)$/
@file_name = $1
return false
elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
@line_num_l = $2.to_i
@line_num_r = $5.to_i
@parsing = true
end
else
if line =~ /^_+$/
self.delete(self.keys.sort.last)
@parsing = false
return false
elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
@line_num_l = $2.to_i
@line_num_r = $5.to_i
else
@nb_line += 1 if parse_line(line, @type)
end
end
return true
end
def inspect
puts '### DIFF TABLE ###'
puts "file : #{file_name}"
self.each do |d|
d.inspect
end
end
private
# Test if is a Side By Side type
def sbs?(type, func)
if @start and type == "sbs"
if @before == func and @second
tmp_nb_line = @nb_line
self[tmp_nb_line] = Diff.new
else
@second = false
tmp_nb_line = @start
@start += 1
@nb_line -= 1
end
else
tmp_nb_line = @nb_line
@start = @nb_line
self[tmp_nb_line] = Diff.new
@second = true
end
unless self[tmp_nb_line]
@nb_line += 1
self[tmp_nb_line] = Diff.new
else
self[tmp_nb_line]
end
end
# Escape the HTML for the diff
def escapeHTML(line)
CGI.escapeHTML(line).gsub(/\s/, '&nbsp;')
end
def parse_line (line, type="inline")
if line[0, 1] == "+"
diff = sbs? type, 'add'
@before = 'add'
diff.line_left = escapeHTML line[1..-1]
diff.nb_line_left = @line_num_l
diff.type_diff_left = 'diff_in'
@line_num_l += 1
true
elsif line[0, 1] == "-"
diff = sbs? type, 'remove'
@before = 'remove'
diff.line_right = escapeHTML line[1..-1]
diff.nb_line_right = @line_num_r
diff.type_diff_right = 'diff_out'
@line_num_r += 1
true
elsif line[0, 1] =~ /\s/
@before = 'same'
@start = false
diff = Diff.new
diff.line_right = escapeHTML line[1..-1]
diff.nb_line_right = @line_num_r
diff.line_left = escapeHTML line[1..-1]
diff.nb_line_left = @line_num_l
self[@nb_line] = diff
@line_num_l += 1
@line_num_r += 1
true
else
false
end
end
end
end

33
app/models/time_entry.rb Normal file
View File

@@ -0,0 +1,33 @@
class TimeEntry < ActiveRecord::Base
# could have used polymorphic association
# project association here allows easy loading of time entries at project level with one database trip
belongs_to :project
belongs_to :issue
belongs_to :user
belongs_to :activity, :class_name => 'Enumeration', :foreign_key => :activity_id
attr_protected :project_id, :user_id, :tyear, :tmonth, :tweek
validates_presence_of :user_id, :activity_id, :project_id, :hours, :spent_on
validates_numericality_of :hours, :allow_nil => true
validates_length_of :comment, :maximum => 255
def before_validation
self.project = issue.project if issue && project.nil?
end
def validate
errors.add :hours, :activerecord_error_invalid if hours && (hours < 0 || hours >= 1000)
errors.add :project_id, :activerecord_error_invalid if project.nil?
errors.add :issue_id, :activerecord_error_invalid if (issue_id && !issue) || (issue && project!=issue.project)
end
# tyear, tmonth, tweek assigned where setting spent_on attributes
# these attributes make time aggregations easier
def spent_on=(date)
super
self.tyear = spent_on ? spent_on.year : nil
self.tmonth = spent_on ? spent_on.month : nil
self.tweek = spent_on ? spent_on.cweek : nil
end
end

View File

@@ -31,7 +31,7 @@ class Token < ActiveRecord::Base
# Delete all expired tokens
def self.destroy_expired
Token.delete_all ["created_on < ?", Time.now - @@validity_time]
Token.delete_all ["action <> 'feeds' AND created_on < ?", Time.now - @@validity_time]
end
private

View File

@@ -1,31 +1,33 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Tracker < ActiveRecord::Base
before_destroy :check_integrity
has_many :issues
has_many :workflows, :dependent => true
has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => 'custom_fields_trackers', :association_foreign_key => 'custom_field_id'
validates_presence_of :name
validates_uniqueness_of :name
private
def check_integrity
raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id])
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Tracker < ActiveRecord::Base
before_destroy :check_integrity
has_many :issues
has_many :workflows, :dependent => :delete_all
has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => "#{table_name_prefix}custom_fields_trackers#{table_name_suffix}", :association_foreign_key => 'custom_field_id'
acts_as_list
validates_presence_of :name
validates_uniqueness_of :name
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
private
def check_integrity
raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id])
end
end

View File

@@ -1,115 +1,154 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require "digest/sha1"
class User < ActiveRecord::Base
has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :dependent => true
has_many :custom_values, :dependent => true, :as => :customized
belongs_to :auth_source
attr_accessor :password, :password_confirmation
attr_accessor :last_before_login_on
# Prevents unauthorized assignments
attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
validates_presence_of :login, :firstname, :lastname, :mail
validates_uniqueness_of :login, :mail
# Login must contain lettres, numbers, underscores only
validates_format_of :login, :with => /^[a-z0-9_]+$/i
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
# Password length between 4 and 12
validates_length_of :password, :in => 4..12, :allow_nil => true
validates_confirmation_of :password, :allow_nil => true
validates_associated :custom_values, :on => :update
# Account statuses
STATUS_ACTIVE = 1
STATUS_REGISTERED = 2
STATUS_LOCKED = 3
def before_save
# update hashed_password if password was set
self.hashed_password = User.hash_password(self.password) if self.password
end
# Returns the user that matches provided login and password, or nil
def self.try_to_login(login, password)
user = find(:first, :conditions => ["login=?", login])
if user
# user is already in local database
return nil if !user.active?
if user.auth_source
# user has an external authentication method
return nil unless user.auth_source.authenticate(login, password)
else
# authentication with local password
return nil unless User.hash_password(password) == user.hashed_password
end
else
# user is not yet registered, try to authenticate with available sources
attrs = AuthSource.authenticate(login, password)
if attrs
onthefly = new(*attrs)
onthefly.login = login
onthefly.language = $RDM_DEFAULT_LANG
if onthefly.save
user = find(:first, :conditions => ["login=?", login])
logger.info("User '#{user.login}' created on the fly.") if logger
end
end
end
user.update_attribute(:last_login_on, Time.now) if user
user
rescue => text
raise text
end
# Return user's full name for display
def display_name
firstname + " " + lastname
end
def active?
self.status == STATUS_ACTIVE
end
def locked?
self.status == STATUS_LOCKED
end
def check_password?(clear_password)
User.hash_password(clear_password) == self.hashed_password
end
def role_for_project(project_id)
@role_for_projects ||=
begin
roles = {}
self.memberships.each { |m| roles.store m.project_id, m.role_id }
roles
end
@role_for_projects[project_id]
end
private
# Return password digest
def self.hash_password(clear_password)
Digest::SHA1.hexdigest(clear_password || "")
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require "digest/sha1"
class User < ActiveRecord::Base
has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :dependent => :delete_all
has_many :projects, :through => :memberships
has_many :custom_values, :dependent => :delete_all, :as => :customized
has_one :preference, :dependent => :destroy, :class_name => 'UserPreference'
has_one :rss_key, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'"
belongs_to :auth_source
attr_accessor :password, :password_confirmation
attr_accessor :last_before_login_on
# Prevents unauthorized assignments
attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
validates_presence_of :login, :firstname, :lastname, :mail
validates_uniqueness_of :login, :mail
# Login must contain lettres, numbers, underscores only
validates_format_of :login, :with => /^[a-z0-9_\-@\.]+$/i
validates_length_of :login, :maximum => 30
validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-]*$/i
validates_length_of :firstname, :lastname, :maximum => 30
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
validates_length_of :mail, :maximum => 60
# Password length between 4 and 12
validates_length_of :password, :in => 4..12, :allow_nil => true
validates_confirmation_of :password, :allow_nil => true
validates_associated :custom_values, :on => :update
# Account statuses
STATUS_ACTIVE = 1
STATUS_REGISTERED = 2
STATUS_LOCKED = 3
def before_save
# update hashed_password if password was set
self.hashed_password = User.hash_password(self.password) if self.password
end
def self.active
with_scope :find => { :conditions => [ "status = ?", STATUS_ACTIVE ] } do
yield
end
end
def self.find_active(*args)
active do
find(*args)
end
end
# Returns the user that matches provided login and password, or nil
def self.try_to_login(login, password)
user = find(:first, :conditions => ["login=?", login])
if user
# user is already in local database
return nil if !user.active?
if user.auth_source
# user has an external authentication method
return nil unless user.auth_source.authenticate(login, password)
else
# authentication with local password
return nil unless User.hash_password(password) == user.hashed_password
end
else
# user is not yet registered, try to authenticate with available sources
attrs = AuthSource.authenticate(login, password)
if attrs
onthefly = new(*attrs)
onthefly.login = login
onthefly.language = Setting.default_language
if onthefly.save
user = find(:first, :conditions => ["login=?", login])
logger.info("User '#{user.login}' created on the fly.") if logger
end
end
end
user.update_attribute(:last_login_on, Time.now) if user
user
rescue => text
raise text
end
# Return user's full name for display
def display_name
firstname + " " + lastname
end
def name
display_name
end
def active?
self.status == STATUS_ACTIVE
end
def registered?
self.status == STATUS_REGISTERED
end
def locked?
self.status == STATUS_LOCKED
end
def check_password?(clear_password)
User.hash_password(clear_password) == self.hashed_password
end
def role_for_project(project)
member = memberships.detect {|m| m.project_id == project.id}
member ? member.role : nil
end
def pref
self.preference ||= UserPreference.new(:user => self)
end
def get_or_create_rss_key
self.rss_key || Token.create(:user => self, :action => 'feeds')
end
def self.find_by_rss_key(key)
token = Token.find_by_value(key)
token && token.user.active? ? token.user : nil
end
def <=>(user)
lastname <=> user.lastname
end
private
# Return password digest
def self.hash_password(clear_password)
Digest::SHA1.hexdigest(clear_password || "")
end
end

View File

@@ -1,23 +1,23 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class UserCustomField < CustomField
def type_name
:label_user_plural
end
end
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class UserCustomField < CustomField
def type_name
:label_user_plural
end
end

View File

@@ -0,0 +1,44 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class UserPreference < ActiveRecord::Base
belongs_to :user
serialize :others
attr_protected :others
def initialize(attributes = nil)
super
self.others ||= {}
end
def [](attr_name)
if attribute_present? attr_name
super
else
others[attr_name]
end
end
def []=(attr_name, value)
if attribute_present? attr_name
super
else
others.store attr_name, value
end
end
end

View File

@@ -1,31 +1,40 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Version < ActiveRecord::Base
before_destroy :check_integrity
belongs_to :project
has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id'
has_many :attachments, :as => :container, :dependent => true
validates_presence_of :name
validates_uniqueness_of :name, :scope => [:project_id]
private
def check_integrity
raise "Can't delete version" if self.fixed_issues.find(:first)
end
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Version < ActiveRecord::Base
before_destroy :check_integrity
belongs_to :project
has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id'
has_many :attachments, :as => :container, :dependent => :destroy
validates_presence_of :name
validates_uniqueness_of :name, :scope => [:project_id]
validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :activerecord_error_not_a_date
def start_date
effective_date
end
def due_date
effective_date
end
private
def check_integrity
raise "Can't delete version" if self.fixed_issues.find(:first)
end
end

44
app/models/wiki.rb Normal file
View File

@@ -0,0 +1,44 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Wiki < ActiveRecord::Base
belongs_to :project
has_many :pages, :class_name => 'WikiPage', :dependent => :destroy
validates_presence_of :start_page
# find the page with the given title
# if page doesn't exist, return a new page
def find_or_new_page(title)
title = Wiki.titleize(title || start_page)
find_page(title) || WikiPage.new(:wiki => self, :title => title)
end
# find the page with the given title
def find_page(title)
pages.find_by_title(Wiki.titleize(title || start_page))
end
# turn a string into a valid page title
def self.titleize(title)
# replace spaces with _ and remove unwanted caracters
title = title.gsub(/\s+/, '_').delete(',;|') if title
# upcase the first letter
title = title[0..0].upcase + title[1..-1] if title
title
end
end

View File

@@ -0,0 +1,58 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'zlib'
class WikiContent < ActiveRecord::Base
belongs_to :page, :class_name => 'WikiPage', :foreign_key => 'page_id'
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
validates_presence_of :text
acts_as_versioned
class Version
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
attr_protected :data
def text=(plain)
case Setting.wiki_compression
when 'gzip'
begin
self.data = Zlib::Deflate.deflate(plain, Zlib::BEST_COMPRESSION)
self.compression = 'gzip'
rescue
self.data = plain
self.compression = ''
end
else
self.data = plain
self.compression = ''
end
plain
end
def text
@text ||= case compression
when 'gzip'
Zlib::Inflate.inflate(data)
else
# uncompressed data
data
end
end
end
end

44
app/models/wiki_page.rb Normal file
View File

@@ -0,0 +1,44 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class WikiPage < ActiveRecord::Base
belongs_to :wiki
has_one :content, :class_name => 'WikiContent', :foreign_key => 'page_id', :dependent => :destroy
validates_presence_of :title
validates_format_of :title, :with => /^[^,\s]*$/
validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false
validates_associated :content
def before_save
self.title = Wiki.titleize(title)
end
def pretty_title
WikiPage.pretty_title(title)
end
def content_for_version(version=nil)
result = content.versions.find_by_version(version.to_i) if version
result ||= content
result
end
def self.pretty_title(str)
(str && str.is_a?(String)) ? str.tr('_', ' ') : str
end
end

View File

@@ -1,24 +1,24 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Workflow < ActiveRecord::Base
belongs_to :role
belongs_to :old_status, :class_name => 'IssueStatus', :foreign_key => 'old_status_id'
belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id'
validates_presence_of :role, :old_status, :new_status
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Workflow < ActiveRecord::Base
belongs_to :role
belongs_to :old_status, :class_name => 'IssueStatus', :foreign_key => 'old_status_id'
belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id'
validates_presence_of :role, :old_status, :new_status
end

View File

@@ -0,0 +1,24 @@
<center>
<div class="box login">
<h2 class="icon22 icon22-authent"><%=l(:label_please_login)%></h2>
<% form_tag({:action=> "login"}, :class => "tabular") do %>
<p><label for="login"><%=l(:field_login)%>:</label>
<%= text_field_tag 'login', nil, :size => 25 %></p>
<p><label for="password"><%=l(:field_password)%>:</label>
<%= password_field_tag 'password', nil, :size => 25 %></p>
<p><center><input type="submit" name="login" value="<%=l(:button_login)%> &#187;" class="primary" /></center>
<% end %>
<br>
<% links = []
links << link_to(l(:label_register), :action => 'register') if Setting.self_registration?
links << link_to(l(:label_password_lost), :action => 'lost_password') if Setting.lost_password?
%>
<%= links.join(" | ") %>
</p>
</div>
</center>

View File

@@ -1,14 +1,14 @@
<center>
<div class="box login">
<h2><%=l(:label_password_lost)%></h2>
<%= start_form_tag({:action=> "lost_password"}, :class => "tabular") %>
<p><label for="mail"><%=l(:field_mail)%> <span class="required">*</span></label>
<%= text_field_tag 'mail', nil, :size => 40 %></p>
<p><center><%= submit_tag l(:button_submit) %></center></p>
<%= end_form_tag %>
</div>
<center>
<div class="box login">
<h2><%=l(:label_password_lost)%></h2>
<% form_tag({:action=> "lost_password"}, :class => "tabular") do %>
<p><label for="mail"><%=l(:field_mail)%> <span class="required">*</span></label>
<%= text_field_tag 'mail', nil, :size => 40 %></p>
<p><center><%= submit_tag l(:button_submit) %></center></p>
<% end %>
</div>
</center>

Some files were not shown because too many files have changed in this diff Show More