Compare commits

..
179 Commits
Author SHA1 Message Date
Jean-Philippe Lang 7e6d1b6c35 Version set to 1.2.3.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8178 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-10 14:49:48 +00:00
Jean-Philippe Lang 5c4b618bce CHANGELOG updated.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8177 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-10 14:49:10 +00:00
Jean-Philippe Lang 2f87b3bae3 Merged r7920, r7921, r7922 and r7924 from trunk (#9405).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8158 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-10 12:04:47 +00:00
Jean-Philippe Lang 1848fcd91e Merged r8103 from trunk (#9737).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8157 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-10 11:56:13 +00:00
Jean-Philippe Lang 40a14cafbc Merged r7809 from trunk (#9567).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8120 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:58:58 +00:00
Jean-Philippe Lang f252108f30 Merged r7834 from trunk (#9566).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8119 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:57:55 +00:00
Jean-Philippe Lang 6d57380712 Merged r7780 from trunk (#9552).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8118 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:56:49 +00:00
Jean-Philippe Lang 00d1b230e0 Merged r7814 from trunk (#9577).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8117 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:54:05 +00:00
Jean-Philippe Lang d19a0b70e0 Merged r7971 from trunk (#9682).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8116 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:52:31 +00:00
Jean-Philippe Lang 535b5ccf2b Merged r7919 from trunk (#9448).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8115 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 21:49:52 +00:00
Toshi MARUYAMA a441667b8d Merged r8106 from trunk
remove trailing white-spaces from calendar-hr.js

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8108 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 01:21:54 +00:00
Toshi MARUYAMA d4246334e0 Merged r8105 from trunk
convert calendar-hr.js (Croatian) from Windows-1250 to UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8107 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-07 01:21:06 +00:00
Toshi MARUYAMA c8c48a7816 Merged r8002 from trunk
Bulgarian translation updated by Ivan Cenov.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8083 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-12-04 22:36:12 +00:00
Jean-Philippe Lang fa894328bb Merged r7983 and r7984 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@8000 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:17:41 +00:00
Jean-Philippe Lang 63e2e52dd3 Merged r7782 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7999 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:14:24 +00:00
Jean-Philippe Lang ff75a959e0 Merged r7779 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7998 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:12:58 +00:00
Jean-Philippe Lang 5d1388db02 Merged r7985 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7997 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:11:54 +00:00
Jean-Philippe Lang 3e4d1fb04f Backported r7982 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7996 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:10:45 +00:00
Jean-Philippe Lang 2858979b69 Merged r7956 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7995 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-29 21:08:06 +00:00
Etienne Massip be09ba039b Merged r7837 from trunk (#9597).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7838 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-18 22:30:32 +00:00
Toshi MARUYAMA a5adecb40c Merge r7797 from trunk
Simplified Chinese "text_git_repository_note" translation updated by Steven Wong.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7801 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-13 06:38:41 +00:00
Toshi MARUYAMA f328373ffd Merge r7796 from trunk
Simplified Chinese translation for 1.2.2 updated by Steven Wong.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7800 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-13 06:38:08 +00:00
Toshi MARUYAMA 367ad46911 Merge r7795 from trunk
Simplified Chinese translation changed by Steven Wong.

* field_due_date
* permission_rename_wiki_pages
* button_rename

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7799 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-13 06:37:33 +00:00
Toshi MARUYAMA 909cb9ab78 Merge r6699 from trunk
remove trailing white-spaces from config/locales/zh.yml

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7793 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-13 03:46:53 +00:00
Toshi MARUYAMA 8c2869f521 Merge r6698 from trunk
Ruby 1.9: fix parsing error of zh.yml with psych yaml library

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7792 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-13 03:46:05 +00:00
Jean-Philippe Lang 20e54f46b0 Merged r7776 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7777 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 12:53:35 +00:00
Jean-Philippe Lang 88e918f64d Merged r7774 from trunk (#8615).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7775 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 12:44:13 +00:00
Jean-Philippe Lang b6f0d9da8a Merged r7772 from trunk (#8615).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7773 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 12:33:15 +00:00
Jean-Philippe Lang d6bf26ace7 Merged r6308 from trunk (#8884).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7770 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:44:10 +00:00
Jean-Philippe Lang 21910aa428 Merged r6311 from trunk (#8880).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7769 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:40:56 +00:00
Jean-Philippe Lang f22ff1f1c2 Merged r6298 from trunk (#8865).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7768 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:37:55 +00:00
Jean-Philippe Lang 83a2283b7d Merged r6300 and r6302 from trunk (#8836).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7767 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:36:52 +00:00
Jean-Philippe Lang 03b2162e6c Merged r6324 and r6325 from trunk (#8651).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7766 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:35:03 +00:00
Jean-Philippe Lang c605477da5 Merged r6314 from trunk (#8633).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7765 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-11 11:31:49 +00:00
Toshi MARUYAMA 35ec8e3570 Merged r7731 from trunk
Spanish translation updated by Ismael G Marin C.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7732 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-05 06:57:52 +00:00
Toshi MARUYAMA 6e68bf8ab4 merge r7707 from trunk
add unit test of escaping image urls

Contributed by Holger Just.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7709 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-02 07:41:12 +00:00
Toshi MARUYAMA d181a2221a merge r6759 from trunk
remove trailing white-spaces from test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7708 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-11-02 07:40:49 +00:00
Toshi MARUYAMA e4034bc74b backed out previous 1.2-stable dummy commit
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7703 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-30 03:29:14 +00:00
Toshi MARUYAMA 310d4c52ce dummy commit to run test on CI server
Tests fail on CI Server, but I don't know the reason.
http://www.redmine.org/builds/build_1.2-stable-1.8.7-sqlite3_82.html

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7702 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-30 03:28:46 +00:00
Toshi MARUYAMA 1d1b3fc77d Merged r7699 from trunk
Dutch translation updated by Pieter Nicolai

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7700 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-30 00:05:29 +00:00
Toshi MARUYAMA 5e58434567 Merged r7660 from trunk
scm: git: fix typo of comments about fetching revisions

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7661 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-27 01:37:09 +00:00
Toshi MARUYAMA 8da22803be Merged r7658 from trunk
scm: git: recovery and improve comments of fetching from 1.1
about harmful influence that git does not have the revision number.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7659 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-27 00:41:37 +00:00
Toshi MARUYAMA 83ab216d70 Merged r7650 from trunk
scm: mercurial: drop supporting below Mercurial 1.1

On November 1st 2011, Mercurial 2.0 will be released.

On Mercurial 1.1.2, unit lib test fails with following error.

<pre>
Traceback (most recent call last):
  File "/WEB-DOWN/hg-repo/hg-crew/hg", line 20, in <module>
    mercurial.dispatch.run()
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 20, in run
    sys.exit(dispatch(sys.argv[1:]))
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 29, in dispatch
    return _runcatch(u, args)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 45, in _runcatch
    return _dispatch(ui, args)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 367, in _dispatch
    ret = _runcommand(ui, options, cmd, d)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 416, in _runcommand
    return checkargs()
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 376, in checkargs
    return cmdfunc()
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 361, in <lambda>
    d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/util.py", line 715, in check
    return func(*args, **kwargs)
  File "/REDMINE-1/hg-workdir/redmine-bb-all/lib/redmine/scm/adapters/mercurial/redminehelper.py", line 149, in rhlog
    if hg.util.version() >= '1.6':
AttributeError: 'module' object has no attribute 'version'

  1) Error:
test_nodes_in_branch(MercurialAdapterTest):
Redmine::Scm::Adapters::MercurialAdapter::HgCommandAborted: hg exited with non-zero status: 1
    lib/redmine/scm/adapters/mercurial_adapter.rb:306:in `hg'
    lib/redmine/scm/adapters/mercurial_adapter.rb:234:in `nodes_in_branch'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:311:in `test_nodes_in_branch'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:304:in `each'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:304:in `test_nodes_in_branch'
</pre>

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7651 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-25 07:20:14 +00:00
Toshi MARUYAMA 4104741383 Merged r7643 from trunk
scm: mercurial: skip failing unit model tests on below Mercurial 1.5

Tests of non ASCII nor alphabetic nor numeric *named branch* fails on below Mercurial 1.5.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7647 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-24 11:29:38 +00:00
Toshi MARUYAMA 6dac4a499f Merged r7642 from trunk
scm: mercurial: skip failing unit lib tests on below Mercurial 1.5

Tests of non ASCII nor alphabetic nor numeric *named branch* fails on below Mercurial 1.5.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7646 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-24 11:28:51 +00:00
Toshi MARUYAMA e0a8442b09 Merged r7641 from trunk
scm: mercurial: switch rev parameter of extension rhlog() if above Mercurial 1.6 or not

On Mercurial 1.5, following error raises.

<pre>
hg --config extensions.redminehelper=lib/redmine/scm/adapters/mercurial/redminehelper.py \
  --rhbranch default --from default --to 0

abort: unknown revision '"default"'!
</pre>

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7645 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-24 11:28:19 +00:00
Toshi MARUYAMA 6dd11c9558 Merged r7640 from trunk
scm: mercurial: fix extension cmdtable on Mercurial 1.5

Before Mercurial revision "40c06bbf58be":http://www.selenic.com/repo/hg-stable/rev/40c06bbf58be ,
following error raises.

<pre>
Traceback (most recent call last):
  File "/WEB-DOWN/hg-repo/hg-crew/hg", line 27, in <module>
    mercurial.dispatch.run()
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 16, in run
    sys.exit(dispatch(sys.argv[1:]))
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 30, in dispatch
    return _runcatch(u, args)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 47, in _runcatch
    return _dispatch(ui, args)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 398, in _dispatch
    cmd, func, args, options, cmdoptions = _parse(lui, args)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/dispatch.py", line 277, in _parse
    args = fancyopts.fancyopts(args, c, cmdoptions, True)
  File "/WEB-DOWN/hg-repo/hg-crew/mercurial/fancyopts.py", line 62, in fancyopts
    for short, name, default, comment in options:
ValueError: too many values to unpack

  1) Error:
test_nodes_in_branch(MercurialAdapterTest):
Redmine::Scm::Adapters::MercurialAdapter::HgCommandAborted: hg exited with non-zero status: 1
    lib/redmine/scm/adapters/mercurial_adapter.rb:306:in `hg'
    lib/redmine/scm/adapters/mercurial_adapter.rb:234:in `nodes_in_branch'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:311:in `test_nodes_in_branch'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:304:in `each'
    test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb:304:in `test_nodes_in_branch'
</pre>

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7644 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-24 11:27:38 +00:00
Toshi MARUYAMA 1608ca3d98 Merged r7579 from trunk.
Restrict anonymous read access with Redmine.pm

Redmine.pm now also checks for public projects whether the anonymous
user has the browse_repository right for a read operation.

Contributed by Holger Just.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7580 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-04 21:52:08 +00:00
Etienne Massip 0ef89ee4ea Merged r7570 from trunk (#9245).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7578 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-04 19:29:00 +00:00
Toshi MARUYAMA 4813672728 Merged r7571 from trunk.
Fix typo of fix_issue() at Changeset model.

Contributed by Sylvain Utard.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7572 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-04 10:55:32 +00:00
Etienne Massip ade5409310 Merged r7568 from trunk (#9308).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7569 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-03 20:19:44 +00:00
Etienne Massip 605f1745ff Merged #7563 from trunk (#7215).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7564 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-02 17:28:33 +00:00
Etienne Massip 8158a26ee8 Merged #7560 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7561 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-02 15:35:39 +00:00
Etienne Massip 4682acf040 Merged r7558 from trunk (#3276).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7559 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-10-02 14:52:43 +00:00
Etienne Massip 3955f81b3f Merged r7538 from trunk (#8411).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7539 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-26 17:47:50 +00:00
Etienne Massip 16f56a4677 Merged r7458 from trunk (#7613).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7482 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-23 17:23:22 +00:00
Toshi MARUYAMA f77b83451b Merged r7468 from trunk.
Norwegian translation of trunk r5957 and 1.2-stable r7455 updated.

Contributed by Lars Erik Gullerud.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7471 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-23 10:45:28 +00:00
Toshi MARUYAMA 2f2a93c6ef Merged r7451 and r7454 from trunk.
Slovenian translation updated.

Contributed by Nejc Vidmar.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7455 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-22 14:06:18 +00:00
Toshi MARUYAMA 5c282222a0 Backed out r7442.
Merged r7439 from trunk.

Slovenian translation of trunk r5957 and 1.2-stable r7434 updated.

Contributed by Nejc Vidmar.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7449 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-22 12:28:30 +00:00
Toshi MARUYAMA 61b4f41539 Merged r7439 from trunk.
Slovenian translation of trunk r5957 and 1.2-stable r7434 updated.

Contributed by Nejc Vidmar.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7442 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-22 01:52:04 +00:00
Toshi MARUYAMA 73e27a48e0 Merged r7432 from trunk.
fix typos in lib/redmine/hook.rb.

Contributed by Igor Zubkov.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7434 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-21 09:57:26 +00:00
Toshi MARUYAMA 51d7c568b0 Merged r7407 from trunk.
remove trailing white-spaces from lib/redmine/hook.rb

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7433 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-21 09:56:52 +00:00
Toshi MARUYAMA 51d772de70 Merged r7068 from trunk.
fix typo in imap examples at lib/tasks/email.rake.

Contributed by Nathan L Smith.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7069 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-07 01:07:43 +00:00
Toshi MARUYAMA 86845b1989 Merged r7060 from trunk.
add "ruby test/unit/issue_test.rb" for an each test at doc/RUNNING_TESTS.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7061 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-05 11:45:16 +00:00
Toshi MARUYAMA 723d60a1ce Merge r7033 from trunk.
remove duplicate "test_index_should_not_list_issues_when_module_disabled" from functional issues controller test.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7038 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-02 01:30:33 +00:00
Toshi MARUYAMA b128fcaf0d back out r7036.
I mistook merged revision of the revision comment.
r7035 is wrong. r7033 is correct.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7037 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-02 01:29:54 +00:00
Toshi MARUYAMA 73dd0c49dd Merge r7035 from trunk.
remove duplicate "test_index_should_not_list_issues_when_module_disabled" from functional issues controller test.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@7036 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-09-02 01:15:12 +00:00
Toshi MARUYAMA cc7274f38c Merge r6915 from trunk.
fix grammatical error of field_warn_on_leaving_unsaved in pt-BR.yml.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6916 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-31 14:59:35 +00:00
Toshi MARUYAMA d0f3b8fa4d Merge r6600 from trunk.
Hungarian translation for 1.2.1 updated by Csaba Molnár.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6601 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-24 12:56:36 +00:00
Toshi MARUYAMA 2302955bc5 Merge r6021 from trunk (#8825).
scm: fix JRuby tests fail in unit changeset following test.

* test_invalid_utf8_sequences_in_paths_should_be_replaced

Following Subversion functional tests fail on Japanese Windows + JRuby 1.6.2 (ruby-1.8.7-p330).

* test_directory_diff
* test_revision_diff

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6453 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-17 11:14:03 +00:00
Toshi MARUYAMA 90f83db148 Merged r6005 from trunk.
scm: git: skip non UTF-8 path encoding test of unit model test in JRuby.

Git, Mercurial and CVS path encodings are binary.
Subversion supports URL encoding for path.
Redmine Mercurial adapter and extension use URL encoding.
Git accepts only binary path in command line parameter.
So, there is no way to use binary command line parameter in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6452 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-17 08:16:23 +00:00
Toshi MARUYAMA b6dbf26c86 Merged r6004 from trunk.
scm: git: skip non UTF-8 path encoding test of unit adapter test in JRuby.

Git, Mercurial and CVS path encodings are binary.
Subversion supports URL encoding for path.
Redmine Mercurial adapter and extension use URL encoding.
Git accepts only binary path in command line parameter.
So, there is no way to use binary command line parameter in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6451 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-17 08:16:02 +00:00
Toshi MARUYAMA 8c7e0e279c Merged r6003 from trunk.
scm: git: skip non UTF-8 path encoding test of functional test in JRuby.

Git, Mercurial and CVS path encodings are binary.
Subversion supports URL encoding for path.
Redmine Mercurial adapter and extension use URL encoding.
Git accepts only binary path in command line parameter.
So, there is no way to use binary command line parameter in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6450 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-17 08:15:37 +00:00
Toshi MARUYAMA 6f15634e12 Merged r6447 from trunk.
scm: add comment that configuration of SCM executable command does not work if contains spaces path to configuration.yml.example.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6449 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-16 00:18:14 +00:00
Toshi MARUYAMA 7e837aa34d Merged r6418 from trunk.
remove trailing white-spaces from config/configuration.yml.example.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6448 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-16 00:17:56 +00:00
Toshi MARUYAMA 6c89118bac Merged r6441 from trunk.
PDF: remove unused vendor/plugins/rfpdf/lib/barcode/*.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6443 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 09:57:07 +00:00
Toshi MARUYAMA 260c07eb73 Merged r6435 from trunk.
PDF: remove unused sjis.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6442 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 08:29:47 +00:00
Toshi MARUYAMA 7914381cdd Merged r6434 from trunk.
PDF: remove unused zapfdingbats.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6440 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 07:25:48 +00:00
Toshi MARUYAMA 65ce05326a Merged r6433 from trunk.
PDF: remove unused symbol.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6439 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 07:25:06 +00:00
Toshi MARUYAMA 112c7a1b15 Merged r6432 from trunk.
PDF: remove unused courier.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6438 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 07:24:27 +00:00
Toshi MARUYAMA 23a31dfe27 Merged r6431 from trunk.
PDF: remove unused times*.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6437 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 07:23:43 +00:00
Toshi MARUYAMA 0dc50cb0b1 Merged r6430 from trunk.
PDF: remove unused vera*.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6436 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 07:23:00 +00:00
Toshi MARUYAMA 88163849b4 Merged r6427 from trunk.
PDF: remove unused vera fonts.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6429 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 05:27:03 +00:00
Toshi MARUYAMA 058f36cc6f Merged r6426 from trunk.
PDF: remove unused FreeMono fonts.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6428 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-12 05:26:17 +00:00
Toshi MARUYAMA 11cf38a1a8 Merged r6402 from trunk.
PDF: remove unused DejaVu fonts except DejaVuSans-BoldOblique.

FreeSans has freesansbi.rb. But there is no dejavusansbi.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6408 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-06 00:02:17 +00:00
Toshi MARUYAMA 37d7a9d62d Merged r6401 from trunk.
PDF: remove unused DejaVuSans-ExtraLight font.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6407 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-06 00:01:47 +00:00
Toshi MARUYAMA 1b299369bf Merged r6403 from trunk.
Italian translation for 1.2 updated.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6405 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-08-05 11:24:32 +00:00
Toshi MARUYAMA cbe42633c9 Merged r6282 from trunk.
scm: bazaar: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6294 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:48:38 +00:00
Toshi MARUYAMA 25657168b1 Merged r6281 from trunk.
scm: git: use self.class.sq_bin for command name at adpter scm_cmd().

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6293 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:48:06 +00:00
Toshi MARUYAMA 4852b38efc Merged r6280 from trunk.
scm: git: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6292 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:47:34 +00:00
Toshi MARUYAMA b882993d6a Merged r6279 from trunk.
scm: mercurial: use self.class.sq_bin for command name at adpter scm_cmd().

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6291 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:47:08 +00:00
Toshi MARUYAMA b6c46aa19d Merged r6278 from trunk.
scm: mercurial: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6290 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:46:35 +00:00
Toshi MARUYAMA 0903db52d9 Merged r6277 from trunk.
scm: cvs: use self.class.sq_bin for command name at adpter scm_cmd().

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6289 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:46:01 +00:00
Toshi MARUYAMA 93d256c4a8 Merged r6276 from trunk.
scm: cvs: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6288 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:45:26 +00:00
Toshi MARUYAMA 64a68b86c6 Merged r6275 from trunk.
scm: darcs: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6287 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:44:44 +00:00
Toshi MARUYAMA 1d79bbce44 Merged r6274 from trunk.
scm: subversion: use "shell_quote_command" method at adapter for JRuby + Windows command name.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6286 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:44:07 +00:00
Toshi MARUYAMA 87211bcb75 Merged r6272 from trunk.
scm: add new method "shell_quote_command" at abstract adapter.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6285 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 23:43:22 +00:00
Toshi MARUYAMA 68e97858cb Merge(backport) r6230 from trunk (#8825).
scm: catch all exceptions at adapter shellout() to fork scm command.

If scm command does not exist,
Linux JRuby 1.6.2 (ruby-1.8.7-p330) raises java.io.IOException in production environment.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6273 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-15 11:53:39 +00:00
Jean-Philippe Lang f5a6b0cf93 Updates for 1.2.1 release.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6261 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 11:45:14 +00:00
Toshi MARUYAMA 3cf0bd713d Merged r6247 from trunk.
scm: mercurial: add functional test of destroying invalid repository.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6255 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 02:08:47 +00:00
Toshi MARUYAMA 36bce52f63 Merged r6246 from trunk.
scm: mercurial: do nothing in fetching if info is nil.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6254 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 02:08:23 +00:00
Toshi MARUYAMA 94f5c73746 Merged r6245 from trunk.
scm: mercurial: catch exception and return nil during getting info.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6253 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 02:08:03 +00:00
Toshi MARUYAMA 8b6fd63a59 Merged r6243 from trunk.
scm: mercurial: add functional test of destroying valid repository.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6252 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 02:07:44 +00:00
Toshi MARUYAMA ba6b822e97 Merged r6242 from trunk.
scm: mercurial: add instance variable @project at functional test.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6251 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 02:07:19 +00:00
Toshi MARUYAMA b44044a76a Merge(backport) r6130 from trunk (#8777).
scm: return nil at model default_branch and override at git model.

Redmine Git and Mercurial adapter support *branches*.
Mercurial default branch is *dafault*.
But, it is popular to show all revisions on the top page for Mercurial GUI.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6244 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-11 00:24:22 +00:00
Jean-Philippe Lang eb3a4587c9 Merged r6208 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6209 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 18:49:13 +00:00
Jean-Philippe Lang a8550ba8a6 Merged r6206 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6207 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 12:01:56 +00:00
Jean-Philippe Lang 0527e8cedf Merged r6203 and r6204 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6205 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 11:42:12 +00:00
Jean-Philippe Lang 2a799e8367 Merged r6201 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6202 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 11:26:35 +00:00
Jean-Philippe Lang 3e9ad22fad Merged r6199 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6200 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 10:51:57 +00:00
Jean-Philippe Lang a5bcdf6d2c Backported r6197 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6198 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-09 09:11:13 +00:00
Jean-Philippe Lang 3dcd5d746a Merged r6187 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6188 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-06 19:06:03 +00:00
Jean-Philippe Lang 971aa889f9 Merged r6163, r6171, r6172, r6174 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6175 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-03 15:58:02 +00:00
Jean-Philippe Lang cdc1dfb1e7 Merged r6170 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6173 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-03 15:37:01 +00:00
Jean-Philippe Lang 30255b8054 Merged r6073 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6162 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-03 10:18:18 +00:00
Jean-Philippe Lang 97b697a678 Merged r6126 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6161 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 17:43:08 +00:00
Jean-Philippe Lang 8e87cd6f77 Merged r6147 and r6149 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6160 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 17:29:54 +00:00
Jean-Philippe Lang 65bee7efa3 Merged r6148 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6159 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 17:28:33 +00:00
Jean-Philippe Lang 2325831d81 Merged r5991 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6158 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 17:28:00 +00:00
Jean-Philippe Lang c7f8ea6a37 Merged r5969 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6157 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 17:25:51 +00:00
Toshi MARUYAMA edc4f6d54b PDF: add dummy 'fill' parameter at rfpdf CJK Write method (#8737).
'fill' parameter is already added in trunk by r6131, r6132, r6133.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6156 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 15:44:02 +00:00
Toshi MARUYAMA bf0046b5af PDF: fix ArgumentError MultiCell() in CJK (#8737).
add dummy ln parameter at rfpdf CJK MultiCell method.
ln parameter has already added in trunk by r6131, r6132, r6133.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6155 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 14:59:30 +00:00
Toshi MARUYAMA 3de4afe53a Merged r6146 from trunk.
PDF: add revision number/id of associated revisions on issue PDF.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6153 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 13:15:54 +00:00
Toshi MARUYAMA d15912eb6a Merge(backport) r6136 from trunk (#8737).
PDF: use RDMMultiCell for drawing lines of issue description.

Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6145 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 04:48:07 +00:00
Toshi MARUYAMA 656e651c33 Merge(backport) r6135 from trunk (#8737).
PDF: add 'ln' parameter for drawing lines at RDMMultiCell().

Contributed by Jun NAITOH.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6144 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 04:47:27 +00:00
Toshi MARUYAMA 9543e0a103 Merged r6138 from trunk.
PDF: code clean up lib/redmine/export/pdf.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6143 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-02 04:46:47 +00:00
Toshi MARUYAMA 441f2f216f Merged r6139 from trunk.
Swedish translation updated by Nicklas Holm.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6140 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-07-01 09:02:37 +00:00
Toshi MARUYAMA 15228c9958 Merged r6127 from trunk.
Escape AuthSources in the list.

Contributed by MAEDA, Go

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6128 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-27 23:19:41 +00:00
Jean-Baptiste Barth 5f33a09320 Merged r6124 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6125 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-26 12:51:09 +00:00
Jean-Baptiste Barth 7d77c3544a Merged r6098 from trunk.
Added Project#enable_module! and Project#disable_module!

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6106 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-21 03:35:36 +00:00
Jean-Baptiste Barth 102c9afadf Revert r6104 "Merged r6098 from trunk."
I messed things up with a cherry-pick on master, I'll re-apply it after.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6105 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-21 03:16:49 +00:00
Jean-Baptiste Barth 16ba6bcb77 Merged r6098 from trunk.
Added Project#enable_module! and Project#disable_module!

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6104 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-20 19:39:59 +00:00
Toshi MARUYAMA df37e5cfab Merged r6101 from trunk.
Russian translation update by SERGEY ERSHOV.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6102 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-20 08:54:23 +00:00
Jean-Baptiste Barth f58b86bbb8 Merged r6099 from trunk.
Added a test to ensure 'Project' column can be removed on issues list

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6100 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-20 01:32:18 +00:00
Toshi MARUYAMA 95f68ba6d9 Merged r6096 from trunk.
pt-BR translation update by Enderson Maia.

Better translation to keep a pattern in translations.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6097 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-18 10:17:16 +00:00
Toshi MARUYAMA 171c4b2747 Merged r6094 from trunk.
German translation updated by Jens Martsch.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6095 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-17 07:13:51 +00:00
Toshi MARUYAMA 860a6ce78d Merged r6068 from trunk.
pt-BR translation update by Rodrigo Rosenfeld Rosas.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6069 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-11 21:15:05 +00:00
Toshi MARUYAMA 26d42c26fa Merged r6064 from trunk.
translate field_path_to_repository in pt-BR.yml.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6067 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-11 01:34:32 +00:00
Toshi MARUYAMA c69c434609 Merged r6063 from trunk.
pt-BR translation update by Rodrigo Rosenfeld Rosas.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6066 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-11 01:33:51 +00:00
Toshi MARUYAMA 9381d30ae8 Merged r6062 from trunk.
pt-BR translation update by Enderson Maia.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6065 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-11 01:33:07 +00:00
Toshi MARUYAMA 136bf86307 Merged r6042 from trunk.
scm: mercurial: fix unit adapter annotate test fails on Windows Mercurial 1.8.4+29-e597ef52a7c2.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6046 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-10 08:33:23 +00:00
Toshi MARUYAMA 07f42c53d0 Merged r6041 from trunk.
scm: mercurial: add functional test of annotate file which does not exist in *tip* is not found.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6045 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-10 08:32:42 +00:00
Toshi MARUYAMA 22e143f0b3 Merged r6035 from trunk.
PDF: use DejaVuSans fonts in Vietnamese.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6037 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-10 02:15:47 +00:00
Toshi MARUYAMA 1701de9123 Merged r6034 from trunk.
PDF: back out r6018.

change Vietnamese vi.yml general_pdf_encoding from CP1258 to UTF-8.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6036 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-10 02:15:30 +00:00
Toshi MARUYAMA 0ce6793181 Merged r6031 from trunk.
PDF: fix font name in vendor/plugins/rfpdf/lib/fonts/dejavusansi.rb.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6033 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 23:51:42 +00:00
Toshi MARUYAMA bacc44feab Merged r6030 from trunk.
PDF: Import DejaVu fonts.

http://rfpdf.googlecode.com/files/DejaVu.zip
Sep. 2007
fils size 3,685,721
md5sum: 54274d105b74f817d649035fc1541d8a

rename files.
* DejaVuSans.rb  to dejavusans.rb
* DejaVuSansb.rb to dejavusansb.rb
* DejaVuSansi.rb to dejavusansi.rb

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6032 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 23:44:34 +00:00
Toshi MARUYAMA 4f9a1cd614 Merged r6028 from trunk.
Spanish translation updated by Jorge López.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6029 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 08:06:24 +00:00
Toshi MARUYAMA 44ed963a46 Merged r6024 from trunk.
PDF: replace all non ASCII characters to '?' if Iconv error raise in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6027 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 05:29:23 +00:00
Toshi MARUYAMA 113316cf1e Merged r6023 from trunk.
PDF: use SJIS instead of CP932 at unit pdf test test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_ja in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6026 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 03:51:23 +00:00
Toshi MARUYAMA 17ed97d580 Merged r6022 from trunk.
PDF: use SJIS instead of CP932 at unit pdf test test_rdm_pdf_iconv_cannot_convert_ja_cp932 in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6025 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 03:50:35 +00:00
Toshi MARUYAMA 19c52bc671 Merged r6018 from trunk.
PDF: change Vietnamese vi.yml general_pdf_encoding from UTF-8 to CP1258.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6019 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-09 00:04:11 +00:00
Toshi MARUYAMA d15de8ee12 Merged r6013 from trunk.
PDF: use SJIS instead of CP932 at unit pdf test_fix_text_encoding_nil in JRuby.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6017 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 23:53:42 +00:00
Toshi MARUYAMA 006c82267e Merged r6012 from trunk.
PDF: change Shift_JIS to SHIFT_JIS in lib/redmine/export/pdf.rb for Japanese ja.yml general_pdf_encoding.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6016 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 23:53:24 +00:00
Toshi MARUYAMA 887e7c6781 Merged r6011 from trunk.
PDF: add Japanese comment of ja.yml general_pdf_encoding *CP932* and *SJIS* in JRuby and CRuby (#8565, #61).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6015 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 23:53:03 +00:00
Toshi MARUYAMA 6280d9e9b2 Merged r6010 from trunk.
PDF: add *SJIS* and *Shift_JIS* in lib/redmine/export/pdf.rb for Japanese ja.yml general_pdf_encoding.

JRuby 1.6.2 (ruby-1.8.7-p330) does not support CP932.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6014 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 23:52:43 +00:00
Toshi MARUYAMA 3996d5f42e Merged r6007 from trunk.
scm: add log message of config/configuration.yml if scm command raise Errno::ENOENT exception.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6009 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 13:24:38 +00:00
Toshi MARUYAMA 579abc1802 Merged r6006 from trunk.
scm: code clean up abstract adapter.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6008 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-08 13:23:56 +00:00
Toshi MARUYAMA dc2efa503a Merged r5999 from trunk.
scm: catch all exceptions to get scm command version in repository model.

If scm command does not exist,
Linux jruby 1.6.2 (ruby-1.8.7-p330) raises java.io.IOException in production environment.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@6000 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-03 11:41:34 +00:00
Toshi MARUYAMA 0e6cdeb860 Merged r5992 and r5997 from trunk.
Turkish translation updated by Burak Yiğit Kaya.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5998 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-02 08:26:02 +00:00
Toshi MARUYAMA 3b9ef033bf Backout r5994 Turkish translations.
Tests on CI server fails.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5996 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-02 06:29:15 +00:00
Toshi MARUYAMA 2ae54a0fc1 Merged r5993 from trunk.
change Turkish general_csv_encoding from ISO-8859-1 to ISO-8859-9 by Burak Yiğit Kaya.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5995 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-01 22:55:23 +00:00
Toshi MARUYAMA a87e6e1265 Merged r5992 from trunk.
Turkish translation updated by Burak Yiğit Kaya.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5994 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-01 22:54:58 +00:00
Toshi MARUYAMA 61b1146f9d Merged r5986 from trunk.
German translation updated by Jens Martsch.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5987 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-06-01 08:09:23 +00:00
Toshi MARUYAMA c509c744fd Merged r5970 from trunk.
Traditional Chinese translation updated by ChunChang Lo.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5971 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-31 03:48:27 +00:00
Jean-Philippe Lang 1be21f2413 Merged r5965 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5967 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-30 16:40:52 +00:00
Jean-Philippe Lang eaf430b630 Merged r5964 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5966 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-30 16:40:17 +00:00
Toshi MARUYAMA d2789248f7 Merged r5962 from trunk.
Bulgarian translation updated by Ivan Cenov.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5963 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 14:54:06 +00:00
Jean-Philippe Lang f08f09a9d3 Merged r5950 to r5960 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5961 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 12:06:05 +00:00
Toshi MARUYAMA 2c2760d041 Merged r5887 from trunk.
scm: replace a tab to two spaces in app/views/settings/_repositories.rhtml.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5959 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 11:32:16 +00:00
Toshi MARUYAMA 218e2f32ee Merged r5886 from trunk.
scm: remove trailing white-spaces from app/views/settings/_repositories.rhtml.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5958 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 11:31:48 +00:00
Jean-Philippe Lang f2b01aeb4d Merged r5948 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5949 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 08:15:18 +00:00
Jean-Philippe Lang fabf54a368 Merged r5944 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5947 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 07:47:25 +00:00
Jean-Philippe Lang 6b07f86883 Merged r5881 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5946 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 07:24:15 +00:00
Jean-Philippe Lang 36d2ea9a6c Merged r5880 from trunk.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5945 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-29 07:18:05 +00:00
Toshi MARUYAMA 2dca48be53 Merged r5940 from trunk.
remove trailing white-spaces from rake redmine:email:test task source.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5943 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-28 03:34:47 +00:00
Toshi MARUYAMA 7678aa9445 Merged r5939 from trunk.
handle a nil user in rake redmine:email:test task.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5942 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-28 03:34:23 +00:00
Toshi MARUYAMA 9c355ee6c3 Merged r5938 from trunk.
use rake task parameter style message if redmine:email:test parameter is blank.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5941 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-28 03:33:55 +00:00
Jean-Philippe Lang 723030e40a Set version to stable.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5879 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-22 09:20:14 +00:00
Jean-Philippe Lang e6ed112d9d 1.2-stable branch added.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/1.2-stable@5878 e93f8b46-1217-0410-a6f0-8f06a7374b81
2011-05-22 09:17:45 +00:00
931 changed files with 24517 additions and 25284 deletions
-5
View File
@@ -23,8 +23,3 @@
/tmp/test/* /tmp/test/*
/vendor/rails /vendor/rails
*.rbc *.rbc
/.bundle
/Gemfile.lock
/Gemfile.local
-6
View File
@@ -25,11 +25,5 @@ tmp/sockets/*
tmp/test/* tmp/test/*
vendor/rails vendor/rails
*.rbc *.rbc
.svn/ .svn/
.git/ .git/
.bundle
Gemfile.lock
Gemfile.local
+1 -1
View File
@@ -2,4 +2,4 @@
Redmine is a flexible project management web application written using Ruby on Rails framework. Redmine is a flexible project management web application written using Ruby on Rails framework.
More details can be found in the doc directory or on the official website http://www.redmine.org More details can be found at in the doc directory or on the official website http://www.redmine.org
+2 -7
View File
@@ -5,11 +5,6 @@ require(File.join(File.dirname(__FILE__), 'config', 'boot'))
require 'rake' require 'rake'
require 'rake/testtask' require 'rake/testtask'
require 'rake/rdoctask'
begin require 'tasks/rails'
require 'rdoc/task'
rescue LoadError
# RDoc is not available
end
require 'tasks/rails'
+18 -17
View File
@@ -1,24 +1,24 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2009 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AccountController < ApplicationController class AccountController < ApplicationController
helper :custom_fields helper :custom_fields
include CustomFieldsHelper include CustomFieldsHelper
# prevents login action to be filtered by check_if_login_required application scope filter # prevents login action to be filtered by check_if_login_required application scope filter
skip_before_filter :check_if_login_required skip_before_filter :check_if_login_required
@@ -36,7 +36,7 @@ class AccountController < ApplicationController
logout_user logout_user
redirect_to home_url redirect_to home_url
end end
# Enable user to choose a new password # Enable user to choose a new password
def lost_password def lost_password
redirect_to(home_url) && return unless Setting.lost_password? redirect_to(home_url) && return unless Setting.lost_password?
@@ -51,7 +51,7 @@ class AccountController < ApplicationController
flash[:notice] = l(:notice_account_password_updated) flash[:notice] = l(:notice_account_password_updated)
redirect_to :action => 'login' redirect_to :action => 'login'
return return
end end
end end
render :template => "account/password_recovery" render :template => "account/password_recovery"
return return
@@ -73,7 +73,7 @@ class AccountController < ApplicationController
end end
end end
end end
# User self-registration # User self-registration
def register def register
redirect_to(home_url) && return unless Setting.self_registration? || session[:auth_source_registration] redirect_to(home_url) && return unless Setting.self_registration? || session[:auth_source_registration]
@@ -109,7 +109,7 @@ class AccountController < ApplicationController
end end
end end
end end
# Token based account activation # Token based account activation
def activate def activate
redirect_to(home_url) && return unless Setting.self_registration? && params[:token] redirect_to(home_url) && return unless Setting.self_registration? && params[:token]
@@ -124,9 +124,9 @@ class AccountController < ApplicationController
end end
redirect_to :action => 'login' redirect_to :action => 'login'
end end
private private
def logout_user def logout_user
if User.current.logged? if User.current.logged?
cookies.delete :autologin cookies.delete :autologin
@@ -134,7 +134,7 @@ class AccountController < ApplicationController
self.logged_user = nil self.logged_user = nil
end end
end end
def authenticate_user def authenticate_user
if Setting.openid? && using_open_id? if Setting.openid? && using_open_id?
open_id_authenticate(params[:openid_url]) open_id_authenticate(params[:openid_url])
@@ -156,6 +156,7 @@ class AccountController < ApplicationController
end end
end end
def open_id_authenticate(openid_url) def open_id_authenticate(openid_url)
authenticate_with_open_id(openid_url, :required => [:nickname, :fullname, :email], :return_to => signin_url) do |result, identity_url, registration| authenticate_with_open_id(openid_url, :required => [:nickname, :fullname, :email], :return_to => signin_url) do |result, identity_url, registration|
if result.successful? if result.successful?
@@ -184,7 +185,7 @@ class AccountController < ApplicationController
register_manually_by_administrator(user) do register_manually_by_administrator(user) do
onthefly_creation_failed(user) onthefly_creation_failed(user)
end end
end end
else else
# Existing record # Existing record
if user.active? if user.active?
@@ -196,7 +197,7 @@ class AccountController < ApplicationController
end end
end end
end end
def successful_authentication(user) def successful_authentication(user)
# Valid user # Valid user
self.logged_user = user self.logged_user = user
@@ -207,7 +208,7 @@ class AccountController < ApplicationController
call_hook(:controller_account_success_authentication_after, {:user => user }) call_hook(:controller_account_success_authentication_after, {:user => user })
redirect_back_or_default :controller => 'my', :action => 'page' redirect_back_or_default :controller => 'my', :action => 'page'
end end
def set_autologin_cookie(user) def set_autologin_cookie(user)
token = Token.create(:user => user, :action => 'autologin') token = Token.create(:user => user, :action => 'autologin')
cookie_name = Redmine::Configuration['autologin_cookie_name'] || 'autologin' cookie_name = Redmine::Configuration['autologin_cookie_name'] || 'autologin'
@@ -246,7 +247,7 @@ class AccountController < ApplicationController
yield if block_given? yield if block_given?
end end
end end
# Automatically register a user # Automatically register a user
# #
# Pass a block for behavior when a user fails to save # Pass a block for behavior when a user fails to save
@@ -262,7 +263,7 @@ class AccountController < ApplicationController
yield if block_given? yield if block_given?
end end
end end
# Manual activation by the administrator # Manual activation by the administrator
# #
# Pass a block for behavior when a user fails to save # Pass a block for behavior when a user fails to save
+4 -4
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+17 -26
View File
@@ -26,11 +26,6 @@ class ApplicationController < ActionController::Base
layout 'base' layout 'base'
exempt_from_layout 'builder', 'rsb' exempt_from_layout 'builder', 'rsb'
protect_from_forgery
def handle_unverified_request
super
cookies.delete(:autologin)
end
# Remove broken cookie after upgrade from 0.8.x (#4292) # Remove broken cookie after upgrade from 0.8.x (#4292)
# See https://rails.lighthouseapp.com/projects/8994/tickets/3360 # See https://rails.lighthouseapp.com/projects/8994/tickets/3360
# TODO: remove it when Rails is fixed # TODO: remove it when Rails is fixed
@@ -45,6 +40,7 @@ class ApplicationController < ActionController::Base
before_filter :user_setup, :check_if_login_required, :set_localization before_filter :user_setup, :check_if_login_required, :set_localization
filter_parameter_logging :password filter_parameter_logging :password
protect_from_forgery
rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
rescue_from ::Unauthorized, :with => :deny_access rescue_from ::Unauthorized, :with => :deny_access
@@ -206,6 +202,8 @@ class ApplicationController < ActionController::Base
render_404 unless @object.present? render_404 unless @object.present?
@project = @object.project @project = @object.project
rescue ActiveRecord::RecordNotFound
render_404
end end
def find_model_object def find_model_object
@@ -252,7 +250,7 @@ class ApplicationController < ActionController::Base
if @project.is_public? || User.current.member_of?(@project) || User.current.admin? if @project.is_public? || User.current.member_of?(@project) || User.current.admin?
true true
else else
deny_access User.current.logged? ? render_403 : require_login
end end
else else
@project = nil @project = nil
@@ -312,19 +310,6 @@ class ApplicationController < ActionController::Base
format.json { head @status } format.json { head @status }
end end
end end
# Filter for actions that provide an API response
# but have no HTML representation for non admin users
def require_admin_or_api_request
return true if api_request?
if User.current.admin?
true
elsif User.current.logged?
render_error(:status => 406)
else
deny_access
end
end
# Picks which layout to use based on the request # Picks which layout to use based on the request
# #
@@ -345,10 +330,9 @@ class ApplicationController < ActionController::Base
@items.sort! {|x,y| y.event_datetime <=> x.event_datetime } @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
@items = @items.slice(0, Setting.feeds_limit.to_i) @items = @items.slice(0, Setting.feeds_limit.to_i)
@title = options[:title] || Setting.app_title @title = options[:title] || Setting.app_title
render :template => "common/feed.atom", :layout => false, render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
:content_type => 'application/atom+xml'
end end
# TODO: remove in Redmine 1.4 # TODO: remove in Redmine 1.4
def self.accept_key_auth(*actions) def self.accept_key_auth(*actions)
ActiveSupport::Deprecation.warn "ApplicationController.accept_key_auth is deprecated and will be removed in Redmine 1.4. Use accept_rss_auth (or accept_api_auth) instead." ActiveSupport::Deprecation.warn "ApplicationController.accept_key_auth is deprecated and will be removed in Redmine 1.4. Use accept_rss_auth (or accept_api_auth) instead."
@@ -360,7 +344,7 @@ class ApplicationController < ActionController::Base
ActiveSupport::Deprecation.warn "ApplicationController.accept_key_auth_actions is deprecated and will be removed in Redmine 1.4. Use accept_rss_auth (or accept_api_auth) instead." ActiveSupport::Deprecation.warn "ApplicationController.accept_key_auth_actions is deprecated and will be removed in Redmine 1.4. Use accept_rss_auth (or accept_api_auth) instead."
self.class.accept_rss_auth self.class.accept_rss_auth
end end
def self.accept_rss_auth(*actions) def self.accept_rss_auth(*actions)
if actions.any? if actions.any?
write_inheritable_attribute('accept_rss_auth_actions', actions) write_inheritable_attribute('accept_rss_auth_actions', actions)
@@ -368,11 +352,11 @@ class ApplicationController < ActionController::Base
read_inheritable_attribute('accept_rss_auth_actions') || [] read_inheritable_attribute('accept_rss_auth_actions') || []
end end
end end
def accept_rss_auth?(action=action_name) def accept_rss_auth?(action=action_name)
self.class.accept_rss_auth.include?(action.to_sym) self.class.accept_rss_auth.include?(action.to_sym)
end end
def self.accept_api_auth(*actions) def self.accept_api_auth(*actions)
if actions.any? if actions.any?
write_inheritable_attribute('accept_api_auth_actions', actions) write_inheritable_attribute('accept_api_auth_actions', actions)
@@ -380,7 +364,7 @@ class ApplicationController < ActionController::Base
read_inheritable_attribute('accept_api_auth_actions') || [] read_inheritable_attribute('accept_api_auth_actions') || []
end end
end end
def accept_api_auth?(action=action_name) def accept_api_auth?(action=action_name)
self.class.accept_api_auth.include?(action.to_sym) self.class.accept_api_auth.include?(action.to_sym)
end end
@@ -491,6 +475,13 @@ class ApplicationController < ActionController::Base
render_error "An error occurred while executing the query and has been logged. Please report this error to your Redmine administrator." render_error "An error occurred while executing the query and has been logged. Please report this error to your Redmine administrator."
end end
# Converts the errors on an ActiveRecord object into a common JSON format
def object_errors_to_json(object)
object.errors.collect do |attribute, error|
{ attribute => error }
end.to_json
end
# Renders API response on validation failure # Renders API response on validation failure
def render_validation_errors(object) def render_validation_errors(object)
options = { :status => :unprocessable_entity, :layout => false } options = { :status => :unprocessable_entity, :layout => false }
+9 -22
View File
@@ -20,29 +20,17 @@ class AttachmentsController < ApplicationController
before_filter :file_readable, :read_authorize, :except => :destroy before_filter :file_readable, :read_authorize, :except => :destroy
before_filter :delete_authorize, :only => :destroy before_filter :delete_authorize, :only => :destroy
accept_api_auth :show, :download verify :method => :post, :only => :destroy
def show def show
respond_to do |format| if @attachment.is_diff?
format.html { @diff = File.new(@attachment.diskfile, "rb").read
if @attachment.is_diff? render :action => 'diff'
@diff = File.new(@attachment.diskfile, "rb").read elsif @attachment.is_text? && @attachment.filesize <= Setting.file_max_size_displayed.to_i.kilobyte
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline' @content = File.new(@attachment.diskfile, "rb").read
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type) render :action => 'file'
# Save diff type as user preference else
if User.current.logged? && @diff_type != User.current.pref[:diff_type] download
User.current.pref[:diff_type] = @diff_type
User.current.preference.save
end
render :action => 'diff'
elsif @attachment.is_text? && @attachment.filesize <= Setting.file_max_size_displayed.to_i.kilobyte
@content = File.new(@attachment.diskfile, "rb").read
render :action => 'file'
else
download
end
}
format.api
end end
end end
@@ -58,7 +46,6 @@ class AttachmentsController < ApplicationController
end end
verify :method => :delete, :only => :destroy
def destroy def destroy
# Make sure association callbacks are called # Make sure association callbacks are called
@attachment.container.attachments.delete(@attachment) @attachment.container.attachments.delete(@attachment)
+6 -6
View File
@@ -1,23 +1,23 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AuthSourcesController < ApplicationController class AuthSourcesController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin before_filter :require_admin
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
@@ -58,7 +58,7 @@ class AuthSourcesController < ApplicationController
render 'auth_sources/edit' render 'auth_sources/edit'
end end
end end
def test_connection def test_connection
@auth_method = AuthSource.find(params[:id]) @auth_method = AuthSource.find(params[:id])
begin begin
+1 -1
View File
@@ -1,6 +1,6 @@
class AutoCompletesController < ApplicationController class AutoCompletesController < ApplicationController
before_filter :find_project before_filter :find_project
def issues def issues
@issues = [] @issues = []
q = params[:q].to_s q = params[:q].to_s
+8 -10
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -26,7 +26,7 @@ class BoardsController < ApplicationController
include SortHelper include SortHelper
helper :watchers helper :watchers
include WatchersHelper include WatchersHelper
def index def index
@boards = @project.boards @boards = @project.boards
# show the board if there is only one # show the board if there is only one
@@ -43,7 +43,7 @@ class BoardsController < ApplicationController
sort_update 'created_on' => "#{Message.table_name}.created_on", sort_update 'created_on' => "#{Message.table_name}.created_on",
'replies' => "#{Message.table_name}.replies_count", 'replies' => "#{Message.table_name}.replies_count",
'updated_on' => "#{Message.table_name}.updated_on" 'updated_on' => "#{Message.table_name}.updated_on"
@topic_count = @board.topics.count @topic_count = @board.topics.count
@topic_pages = Paginator.new self, @topic_count, per_page_option, params['page'] @topic_pages = Paginator.new self, @topic_count, per_page_option, params['page']
@topics = @board.topics.find :all, :order => ["#{Message.table_name}.sticky DESC", sort_clause].compact.join(', '), @topics = @board.topics.find :all, :order => ["#{Message.table_name}.sticky DESC", sort_clause].compact.join(', '),
@@ -61,12 +61,11 @@ class BoardsController < ApplicationController
} }
end end
end end
verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :index } verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :index }
def new def new
@board = Board.new @board = Board.new(params[:board])
@board.safe_attributes = params[:board]
@board.project = @project @board.project = @project
if request.post? && @board.save if request.post? && @board.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
@@ -75,8 +74,7 @@ class BoardsController < ApplicationController
end end
def edit def edit
@board.safe_attributes = params[:board] if request.post? && @board.update_attributes(params[:board])
if request.post? && @board.save
redirect_to_settings_in_projects redirect_to_settings_in_projects
end end
end end
@@ -85,7 +83,7 @@ class BoardsController < ApplicationController
@board.destroy @board.destroy
redirect_to_settings_in_projects redirect_to_settings_in_projects
end end
private private
def redirect_to_settings_in_projects def redirect_to_settings_in_projects
redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards' redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards'
+6 -6
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -33,11 +33,11 @@ class CalendarsController < ApplicationController
@year = params[:year].to_i @year = params[:year].to_i
if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
@month = params[:month].to_i @month = params[:month].to_i
end end
end end
@year ||= Date.today.year @year ||= Date.today.year
@month ||= Date.today.month @month ||= Date.today.month
@calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), current_language, :month) @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), current_language, :month)
retrieve_query retrieve_query
@query.group_by = nil @query.group_by = nil
@@ -47,10 +47,10 @@ class CalendarsController < ApplicationController
:conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?))", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt] :conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?))", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
) )
events += @query.versions(:conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt]) events += @query.versions(:conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
@calendar.events = events @calendar.events = events
end end
render :action => 'show', :layout => false if request.xhr? render :action => 'show', :layout => false if request.xhr?
end end
end end
+3 -4
View File
@@ -7,13 +7,12 @@ class CommentsController < ApplicationController
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create def create
@comment = Comment.new @comment = Comment.new(params[:comment])
@comment.safe_attributes = params[:comment]
@comment.author = User.current @comment.author = User.current
if @news.comments << @comment if @news.comments << @comment
flash[:notice] = l(:label_comment_added) flash[:notice] = l(:label_comment_added)
end end
redirect_to :controller => 'news', :action => 'show', :id => @news redirect_to :controller => 'news', :action => 'show', :id => @news
end end
@@ -33,5 +32,5 @@ class CommentsController < ApplicationController
@comment = nil @comment = nil
@news @news
end end
end end
+8 -11
View File
@@ -1,10 +1,10 @@
class ContextMenusController < ApplicationController class ContextMenusController < ApplicationController
helper :watchers helper :watchers
helper :issues helper :issues
def issues def issues
@issues = Issue.visible.all(:conditions => {:id => params[:ids]}, :include => :project) @issues = Issue.visible.all(:conditions => {:id => params[:ids]}, :include => :project)
if (@issues.size == 1) if (@issues.size == 1)
@issue = @issues.first @issue = @issues.first
@allowed_statuses = @issue.new_statuses_allowed_to(User.current) @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@@ -26,22 +26,19 @@ class ContextMenusController < ApplicationController
:delete => User.current.allowed_to?(:delete_issues, @projects) :delete => User.current.allowed_to?(:delete_issues, @projects)
} }
if @project if @project
if @issue @assignables = @project.assignable_users
@assignables = @issue.assignable_users @assignables << @issue.assigned_to if @issue && @issue.assigned_to && !@assignables.include?(@issue.assigned_to)
else
@assignables = @project.assignable_users
end
@trackers = @project.trackers @trackers = @project.trackers
else else
#when multiple projects, we only keep the intersection of each set #when multiple projects, we only keep the intersection of each set
@assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a} @assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a}
@trackers = @projects.map(&:trackers).inject{|memo,t| memo & t} @trackers = @projects.map(&:trackers).inject{|memo,t| memo & t}
end end
@priorities = IssuePriority.active.reverse @priorities = IssuePriority.all.reverse
@statuses = IssueStatus.find(:all, :order => 'position') @statuses = IssueStatus.find(:all, :order => 'position')
@back = back_url @back = back_url
render :layout => false render :layout => false
end end
@@ -56,5 +53,5 @@ class ContextMenusController < ApplicationController
} }
@back = back_url @back = back_url
render :layout => false render :layout => false
end end
end end
+7 -7
View File
@@ -1,30 +1,30 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2009 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomFieldsController < ApplicationController class CustomFieldsController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin before_filter :require_admin
def index def index
@custom_fields_by_type = CustomField.find(:all).group_by {|f| f.class.name } @custom_fields_by_type = CustomField.find(:all).group_by {|f| f.class.name }
@tab = params[:tab] || 'IssueCustomField' @tab = params[:tab] || 'IssueCustomField'
end end
def new def new
@custom_field = begin @custom_field = begin
if params[:type].to_s.match(/.+CustomField$/) if params[:type].to_s.match(/.+CustomField$/)
@@ -33,7 +33,7 @@ class CustomFieldsController < ApplicationController
rescue rescue
end end
(redirect_to(:action => 'index'); return) unless @custom_field.is_a?(CustomField) (redirect_to(:action => 'index'); return) unless @custom_field.is_a?(CustomField)
if request.post? and @custom_field.save if request.post? and @custom_field.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field) call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
@@ -53,7 +53,7 @@ class CustomFieldsController < ApplicationController
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
end end
end end
def destroy def destroy
@custom_field = CustomField.find(params[:id]).destroy @custom_field = CustomField.find(params[:id]).destroy
redirect_to :action => 'index', :tab => @custom_field.class.name redirect_to :action => 'index', :tab => @custom_field.class.name
+13 -15
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -22,9 +22,9 @@ class DocumentsController < ApplicationController
before_filter :find_model_object, :except => [:index, :new] before_filter :find_model_object, :except => [:index, :new]
before_filter :find_project_from_association, :except => [:index, :new] before_filter :find_project_from_association, :except => [:index, :new]
before_filter :authorize before_filter :authorize
helper :attachments helper :attachments
def index def index
@sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category' @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
documents = @project.documents.find :all, :include => [:attachments, :category] documents = @project.documents.find :all, :include => [:attachments, :category]
@@ -41,14 +41,13 @@ class DocumentsController < ApplicationController
@document = @project.documents.build @document = @project.documents.build
render :layout => false if request.xhr? render :layout => false if request.xhr?
end end
def show def show
@attachments = @document.attachments.find(:all, :order => "created_on DESC") @attachments = @document.attachments.find(:all, :order => "created_on DESC")
end end
def new def new
@document = @project.documents.build @document = @project.documents.build(params[:document])
@document.safe_attributes = params[:document]
if request.post? and @document.save if request.post? and @document.save
attachments = Attachment.attach_files(@document, params[:attachments]) attachments = Attachment.attach_files(@document, params[:attachments])
render_attachment_warning_if_needed(@document) render_attachment_warning_if_needed(@document)
@@ -56,21 +55,20 @@ class DocumentsController < ApplicationController
redirect_to :action => 'index', :project_id => @project redirect_to :action => 'index', :project_id => @project
end end
end end
def edit def edit
@categories = DocumentCategory.active #TODO: use it in the views @categories = DocumentCategory.all
@document.safe_attributes = params[:document] if request.post? and @document.update_attributes(params[:document])
if request.post? and @document.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'show', :id => @document redirect_to :action => 'show', :id => @document
end end
end end
def destroy def destroy
@document.destroy @document.destroy
redirect_to :controller => 'documents', :action => 'index', :project_id => @project redirect_to :controller => 'documents', :action => 'index', :project_id => @project
end end
def add_attachment def add_attachment
attachments = Attachment.attach_files(@document, params[:attachments]) attachments = Attachment.attach_files(@document, params[:attachments])
render_attachment_warning_if_needed(@document) render_attachment_warning_if_needed(@document)
+17 -11
View File
@@ -1,39 +1,45 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class EnumerationsController < ApplicationController class EnumerationsController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin before_filter :require_admin
helper :custom_fields helper :custom_fields
include CustomFieldsHelper include CustomFieldsHelper
def index def index
list
render :action => 'list'
end end
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy, :create, :update ], verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :index } :redirect_to => { :action => :list }
def list
end
def new def new
begin begin
@enumeration = params[:type].constantize.new @enumeration = params[:type].constantize.new
rescue NameError rescue NameError
@enumeration = Enumeration.new @enumeration = Enumeration.new
end end
end end
@@ -42,7 +48,7 @@ class EnumerationsController < ApplicationController
@enumeration.type = params[:enumeration][:type] @enumeration.type = params[:enumeration][:type]
if @enumeration.save if @enumeration.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'index', :type => @enumeration.type redirect_to :action => 'list', :type => @enumeration.type
else else
render :action => 'new' render :action => 'new'
end end
@@ -57,12 +63,12 @@ class EnumerationsController < ApplicationController
@enumeration.type = params[:enumeration][:type] if params[:enumeration][:type] @enumeration.type = params[:enumeration][:type] if params[:enumeration][:type]
if @enumeration.update_attributes(params[:enumeration]) if @enumeration.update_attributes(params[:enumeration])
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'index', :type => @enumeration.type redirect_to :action => 'list', :type => @enumeration.type
else else
render :action => 'edit' render :action => 'edit'
end end
end end
def destroy def destroy
@enumeration = Enumeration.find(params[:id]) @enumeration = Enumeration.find(params[:id])
if !@enumeration.in_use? if !@enumeration.in_use?
+5 -5
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -29,16 +29,16 @@ class GanttsController < ApplicationController
helper :sort helper :sort
include SortHelper include SortHelper
include Redmine::Export::PDF include Redmine::Export::PDF
def show def show
@gantt = Redmine::Helpers::Gantt.new(params) @gantt = Redmine::Helpers::Gantt.new(params)
@gantt.project = @project @gantt.project = @project
retrieve_query retrieve_query
@query.group_by = nil @query.group_by = nil
@gantt.query = @query if @query.valid? @gantt.query = @query if @query.valid?
basename = (@project ? "#{@project.identifier}-" : '') + 'gantt' basename = (@project ? "#{@project.identifier}-" : '') + 'gantt'
respond_to do |format| respond_to do |format|
format.html { render :action => "show", :layout => !request.xhr? } format.html { render :action => "show", :layout => !request.xhr? }
format.png { send_data(@gantt.to_image, :disposition => 'inline', :type => 'image/png', :filename => "#{basename}.png") } if @gantt.respond_to?('to_image') format.png { send_data(@gantt.to_image, :disposition => 'inline', :type => 'image/png', :filename => "#{basename}.png") } if @gantt.respond_to?('to_image')
+17 -19
View File
@@ -1,27 +1,27 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2009 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class GroupsController < ApplicationController class GroupsController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin before_filter :require_admin
helper :custom_fields helper :custom_fields
# GET /groups # GET /groups
# GET /groups.xml # GET /groups.xml
def index def index
@@ -48,7 +48,7 @@ class GroupsController < ApplicationController
# GET /groups/new.xml # GET /groups/new.xml
def new def new
@group = Group.new @group = Group.new
respond_to do |format| respond_to do |format|
format.html # new.html.erb format.html # new.html.erb
format.xml { render :xml => @group } format.xml { render :xml => @group }
@@ -67,10 +67,8 @@ class GroupsController < ApplicationController
respond_to do |format| respond_to do |format|
if @group.save if @group.save
format.html { flash[:notice] = l(:notice_successful_create)
flash[:notice] = l(:notice_successful_create) format.html { redirect_to(groups_path) }
redirect_to(params[:continue] ? new_group_path : groups_path)
}
format.xml { render :xml => @group, :status => :created, :location => @group } format.xml { render :xml => @group, :status => :created, :location => @group }
else else
format.html { render :action => "new" } format.html { render :action => "new" }
@@ -107,37 +105,37 @@ class GroupsController < ApplicationController
format.xml { head :ok } format.xml { head :ok }
end end
end end
def add_users def add_users
@group = Group.find(params[:id]) @group = Group.find(params[:id])
users = User.find_all_by_id(params[:user_ids]) users = User.find_all_by_id(params[:user_ids])
@group.users << users if request.post? @group.users << users if request.post?
respond_to do |format| respond_to do |format|
format.html { redirect_to :controller => 'groups', :action => 'edit', :id => @group, :tab => 'users' } format.html { redirect_to :controller => 'groups', :action => 'edit', :id => @group, :tab => 'users' }
format.js { format.js {
render(:update) {|page| render(:update) {|page|
page.replace_html "tab-content-users", :partial => 'groups/users' page.replace_html "tab-content-users", :partial => 'groups/users'
users.each {|user| page.visual_effect(:highlight, "user-#{user.id}") } users.each {|user| page.visual_effect(:highlight, "user-#{user.id}") }
} }
} }
end end
end end
def remove_user def remove_user
@group = Group.find(params[:id]) @group = Group.find(params[:id])
@group.users.delete(User.find(params[:user_id])) if request.delete? @group.users.delete(User.find(params[:user_id])) if request.post?
respond_to do |format| respond_to do |format|
format.html { redirect_to :controller => 'groups', :action => 'edit', :id => @group, :tab => 'users' } format.html { redirect_to :controller => 'groups', :action => 'edit', :id => @group, :tab => 'users' }
format.js { render(:update) {|page| page.replace_html "tab-content-users", :partial => 'groups/users'} } format.js { render(:update) {|page| page.replace_html "tab-content-users", :partial => 'groups/users'} }
end end
end end
def autocomplete_for_user def autocomplete_for_user
@group = Group.find(params[:id]) @group = Group.find(params[:id])
@users = User.active.not_in_group(@group).like(params[:q]).all(:limit => 100) @users = User.active.not_in_group(@group).like(params[:q]).all(:limit => 100)
render :layout => false render :layout => false
end end
def edit_membership def edit_membership
@group = Group.find(params[:id]) @group = Group.find(params[:id])
@membership = Member.edit_membership(params[:membership_id], params[:membership], @group) @membership = Member.edit_membership(params[:membership_id], params[:membership], @group)
@@ -160,7 +158,7 @@ class GroupsController < ApplicationController
end end
end end
end end
def destroy_membership def destroy_membership
@group = Group.find(params[:id]) @group = Group.find(params[:id])
Member.find(params[:membership_id]).destroy if request.post? Member.find(params[:membership_id]).destroy if request.post?
+42 -79
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -18,95 +18,58 @@
class IssueCategoriesController < ApplicationController class IssueCategoriesController < ApplicationController
menu_item :settings menu_item :settings
model_object IssueCategory model_object IssueCategory
before_filter :find_model_object, :except => [:index, :new, :create] before_filter :find_model_object, :except => :new
before_filter :find_project_from_association, :except => [:index, :new, :create] before_filter :find_project_from_association, :except => :new
before_filter :find_project, :only => [:index, :new, :create] before_filter :find_project, :only => :new
before_filter :authorize before_filter :authorize
accept_api_auth :index, :show, :create, :update, :destroy
def index verify :method => :post, :only => :destroy
respond_to do |format|
format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project }
format.api { @categories = @project.issue_categories.all }
end
end
def show
respond_to do |format|
format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project }
format.api
end
end
def new def new
@category = @project.issue_categories.build @category = @project.issue_categories.build(params[:category])
@category.safe_attributes = params[:issue_category] if request.post?
end if @category.save
respond_to do |format|
verify :method => :post, :only => :create format.html do
def create flash[:notice] = l(:notice_successful_create)
@category = @project.issue_categories.build redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project
@category.safe_attributes = params[:issue_category] end
if @category.save format.js do
respond_to do |format| # IE doesn't support the replace_html rjs method for select box options
format.html do render(:update) {|page| page.replace "issue_category_id",
flash[:notice] = l(:notice_successful_create) content_tag('select', '<option></option>' + options_from_collection_for_select(@project.issue_categories, 'id', 'name', @category.id), :id => 'issue_category_id', :name => 'issue[category_id]')
redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project }
end
end end
format.js do else
# IE doesn't support the replace_html rjs method for select box options respond_to do |format|
render(:update) {|page| page.replace "issue_category_id", format.html
content_tag('select', '<option></option>' + options_from_collection_for_select(@project.issue_categories, 'id', 'name', @category.id), :id => 'issue_category_id', :name => 'issue[category_id]') format.js do
} render(:update) {|page| page.alert(@category.errors.full_messages.join('\n')) }
end
end end
format.api { render :action => 'show', :status => :created, :location => issue_category_path(@category) }
end
else
respond_to do |format|
format.html { render :action => 'new'}
format.js do
render(:update) {|page| page.alert(@category.errors.full_messages.join('\n')) }
end
format.api { render_validation_errors(@category) }
end end
end end
end end
def edit def edit
end if request.post? and @category.update_attributes(params[:category])
flash[:notice] = l(:notice_successful_update)
verify :method => :put, :only => :update redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project
def update
@category.safe_attributes = params[:issue_category]
if @category.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project
}
format.api { head :ok }
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@category) }
end
end end
end end
verify :method => :delete, :only => :destroy
def destroy def destroy
@issue_count = @category.issues.size @issue_count = @category.issues.size
if @issue_count == 0 || params[:todo] || api_request? if @issue_count == 0
reassign_to = nil # No issue assigned to this category
if params[:reassign_to_id] && (params[:todo] == 'reassign' || params[:todo].blank?) @category.destroy
reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id]) redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories'
end return
elsif params[:todo]
reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id]) if params[:todo] == 'reassign'
@category.destroy(reassign_to) @category.destroy(reassign_to)
respond_to do |format| redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories'
format.html { redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'categories' }
format.api { head :ok }
end
return return
end end
@categories = @project.issue_categories - [@category] @categories = @project.issue_categories - [@category]
@@ -118,8 +81,8 @@ private
def find_model_object def find_model_object
super super
@category = @object @category = @object
end end
def find_project def find_project
@project = Project.find(params[:project_id]) @project = Project.find(params[:project_id])
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
-19
View File
@@ -1,23 +1,4 @@
# Redmine - project management software
# Copyright (C) 2006-2011 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 IssueMovesController < ApplicationController class IssueMovesController < ApplicationController
menu_item :issues
default_search_scope :issues default_search_scope :issues
before_filter :find_issues, :check_project_uniqueness before_filter :find_issues, :check_project_uniqueness
before_filter :authorize before_filter :authorize
+22 -55
View File
@@ -1,53 +1,30 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueRelationsController < ApplicationController class IssueRelationsController < ApplicationController
before_filter :find_issue, :find_project_from_association, :authorize, :only => [:index, :create] before_filter :find_issue, :find_project_from_association, :authorize
before_filter :find_relation, :except => [:index, :create]
def new
accept_api_auth :index, :show, :create, :destroy
def index
@relations = @issue.relations
respond_to do |format|
format.html { render :nothing => true }
format.api
end
end
def show
raise Unauthorized unless @relation.visible?
respond_to do |format|
format.html { render :nothing => true }
format.api
end
end
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create
@relation = IssueRelation.new(params[:relation]) @relation = IssueRelation.new(params[:relation])
@relation.issue_from = @issue @relation.issue_from = @issue
if params[:relation] && m = params[:relation][:issue_to_id].to_s.match(/^#?(\d+)$/) if params[:relation] && m = params[:relation][:issue_to_id].to_s.match(/^#?(\d+)$/)
@relation.issue_to = Issue.visible.find_by_id(m[1].to_i) @relation.issue_to = Issue.visible.find_by_id(m[1].to_i)
end end
saved = @relation.save @relation.save if request.post?
respond_to do |format| respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue } format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
format.js do format.js do
@@ -60,38 +37,28 @@ class IssueRelationsController < ApplicationController
end end
end end
end end
format.api { end
if saved end
render :action => 'show', :status => :created, :location => relation_url(@relation)
else def destroy
render_validation_errors(@relation) relation = IssueRelation.find(params[:id])
end if request.post? && @issue.relations.include?(relation)
relation.destroy
@issue.reload
end
respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
format.js {
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
render(:update) {|page| page.replace_html "relations", :partial => 'issues/relations'}
} }
end end
end end
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
def destroy
raise Unauthorized unless @relation.deletable?
@relation.destroy
respond_to do |format|
format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
format.js { render(:update) {|page| page.remove "relation-#{@relation.id}"} }
format.api { head :ok }
end
end
private private
def find_issue def find_issue
@issue = @object = Issue.find(params[:issue_id]) @issue = @object = Issue.find(params[:issue_id])
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
def find_relation
@relation = IssueRelation.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end end
+15 -22
View File
@@ -1,37 +1,31 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueStatusesController < ApplicationController class IssueStatusesController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin
before_filter :require_admin, :except => :index verify :method => :post, :only => [ :destroy, :create, :update, :move, :update_issue_done_ratio ],
before_filter :require_admin_or_api_request, :only => :index :redirect_to => { :action => :index }
accept_api_auth :index
def index def index
respond_to do |format| @issue_status_pages, @issue_statuses = paginate :issue_statuses, :per_page => 25, :order => "position"
format.html { render :action => "index", :layout => false if request.xhr?
@issue_status_pages, @issue_statuses = paginate :issue_statuses, :per_page => 25, :order => "position"
render :action => "index", :layout => false if request.xhr?
}
format.api {
@issue_statuses = IssueStatus.all(:order => 'position')
}
end
end end
def new def new
@@ -40,7 +34,7 @@ class IssueStatusesController < ApplicationController
def create def create
@issue_status = IssueStatus.new(params[:issue_status]) @issue_status = IssueStatus.new(params[:issue_status])
if request.post? && @issue_status.save if @issue_status.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'index' redirect_to :action => 'index'
else else
@@ -54,7 +48,7 @@ class IssueStatusesController < ApplicationController
def update def update
@issue_status = IssueStatus.find(params[:id]) @issue_status = IssueStatus.find(params[:id])
if request.put? && @issue_status.update_attributes(params[:issue_status]) if @issue_status.update_attributes(params[:issue_status])
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'index' redirect_to :action => 'index'
else else
@@ -62,7 +56,6 @@ class IssueStatusesController < ApplicationController
end end
end end
verify :method => :delete, :only => :destroy, :redirect_to => { :action => :index }
def destroy def destroy
IssueStatus.find(params[:id]).destroy IssueStatus.find(params[:id]).destroy
redirect_to :action => 'index' redirect_to :action => 'index'
@@ -70,9 +63,9 @@ class IssueStatusesController < ApplicationController
flash[:error] = l(:error_unable_delete_issue_status) flash[:error] = l(:error_unable_delete_issue_status)
redirect_to :action => 'index' redirect_to :action => 'index'
end end
def update_issue_done_ratio def update_issue_done_ratio
if request.post? && IssueStatus.update_issue_done_ratios if IssueStatus.update_issue_done_ratios
flash[:notice] = l(:notice_issue_done_ratios_updated) flash[:notice] = l(:notice_issue_done_ratios_updated)
else else
flash[:error] = l(:error_issue_done_ratios_not_updated) flash[:error] = l(:error_issue_done_ratios_not_updated)
+12 -17
View File
@@ -89,20 +89,15 @@ class IssuesController < ApplicationController
@issue_count_by_group = @query.issue_count_by_group @issue_count_by_group = @query.issue_count_by_group
respond_to do |format| respond_to do |format|
format.html { render :template => 'issues/index', :layout => !request.xhr? } format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
format.api { format.api
Issue.load_relations(@issues) if include_in_api_response?('relations')
}
format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") } format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
format.csv { send_data(issues_to_csv(@issues, @project, @query, params), :type => 'text/csv; header=present', :filename => 'export.csv') } format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') } format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
end end
else else
respond_to do |format| # Send html if the query is not valid
format.html { render(:template => 'issues/index', :layout => !request.xhr?) } render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
format.any(:atom, :csv, :pdf) { render(:nothing => true) }
format.api { render_validation_errors(@query) }
end
end end
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
@@ -121,10 +116,10 @@ class IssuesController < ApplicationController
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? } @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
@allowed_statuses = @issue.new_statuses_allowed_to(User.current) @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@edit_allowed = User.current.allowed_to?(:edit_issues, @project) @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@priorities = IssuePriority.active @priorities = IssuePriority.all
@time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project) @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
respond_to do |format| respond_to do |format|
format.html { render :template => 'issues/show' } format.html { render :template => 'issues/show.rhtml' }
format.api format.api
format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' } format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") } format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
@@ -144,11 +139,11 @@ class IssuesController < ApplicationController
call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue }) call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
if @issue.save if @issue.save
attachments = Attachment.attach_files(@issue, params[:attachments]) attachments = Attachment.attach_files(@issue, params[:attachments])
render_attachment_warning_if_needed(@issue)
flash[:notice] = l(:notice_successful_create)
call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue}) call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
respond_to do |format| respond_to do |format|
format.html { format.html {
render_attachment_warning_if_needed(@issue)
flash[:notice] = l(:notice_issue_successful_create, :id => "<a href='#{issue_path(@issue)}'>##{@issue.id}</a>")
redirect_to(params[:continue] ? { :action => 'new', :project_id => @project, :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } : redirect_to(params[:continue] ? { :action => 'new', :project_id => @project, :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } :
{ :action => 'show', :id => @issue }) { :action => 'show', :id => @issue })
} }
@@ -285,7 +280,7 @@ private
# TODO: Refactor, not everything in here is needed by #edit # TODO: Refactor, not everything in here is needed by #edit
def update_issue_from_params def update_issue_from_params
@allowed_statuses = @issue.new_statuses_allowed_to(User.current) @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@priorities = IssuePriority.active @priorities = IssuePriority.all
@edit_allowed = User.current.allowed_to?(:edit_issues, @project) @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project) @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
@time_entry.attributes = params[:time_entry] @time_entry.attributes = params[:time_entry]
@@ -314,14 +309,14 @@ private
render_error l(:error_no_tracker_in_project) render_error l(:error_no_tracker_in_project)
return false return false
end end
@issue.start_date ||= Date.today if Setting.default_issue_start_date_to_creation_date? @issue.start_date ||= Date.today
if params[:issue].is_a?(Hash) if params[:issue].is_a?(Hash)
@issue.safe_attributes = params[:issue] @issue.safe_attributes = params[:issue]
if User.current.allowed_to?(:add_issue_watchers, @project) && @issue.new_record? if User.current.allowed_to?(:add_issue_watchers, @project) && @issue.new_record?
@issue.watcher_user_ids = params[:issue]['watcher_user_ids'] @issue.watcher_user_ids = params[:issue]['watcher_user_ids']
end end
end end
@priorities = IssuePriority.active @priorities = IssuePriority.all
@allowed_statuses = @issue.new_statuses_allowed_to(User.current, true) @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
end end
+12 -12
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -22,7 +22,7 @@ class JournalsController < ApplicationController
before_filter :authorize, :only => [:new, :edit, :diff] before_filter :authorize, :only => [:new, :edit, :diff]
accept_rss_auth :index accept_rss_auth :index
menu_item :issues menu_item :issues
helper :issues helper :issues
helper :custom_fields helper :custom_fields
helper :queries helper :queries
@@ -34,9 +34,9 @@ class JournalsController < ApplicationController
retrieve_query retrieve_query
sort_init 'id', 'desc' sort_init 'id', 'desc'
sort_update(@query.sortable_columns) sort_update(@query.sortable_columns)
if @query.valid? if @query.valid?
@journals = @query.journals(:order => "#{Journal.table_name}.created_on DESC", @journals = @query.journals(:order => "#{Journal.table_name}.created_on DESC",
:limit => 25) :limit => 25)
end end
@title = (@project ? @project.name : Setting.app_title) + ": " + (@query.new_record? ? l(:label_changes_details) : @query.name) @title = (@project ? @project.name : Setting.app_title) + ": " + (@query.new_record? ? l(:label_changes_details) : @query.name)
@@ -44,7 +44,7 @@ class JournalsController < ApplicationController
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
def diff def diff
@issue = @journal.issue @issue = @journal.issue
if params[:detail_id].present? if params[:detail_id].present?
@@ -55,7 +55,7 @@ class JournalsController < ApplicationController
(render_404; return false) unless @issue && @detail (render_404; return false) unless @issue && @detail
@diff = Redmine::Helpers::Diff.new(@detail.value, @detail.old_value) @diff = Redmine::Helpers::Diff.new(@detail.value, @detail.old_value)
end end
def new def new
journal = Journal.find(params[:journal_id]) if params[:journal_id] journal = Journal.find(params[:journal_id]) if params[:journal_id]
if journal if journal
@@ -69,7 +69,7 @@ class JournalsController < ApplicationController
text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]') text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
content = "#{ll(Setting.default_language, :text_user_wrote, user)}\n> " content = "#{ll(Setting.default_language, :text_user_wrote, user)}\n> "
content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n" content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
render(:update) { |page| render(:update) { |page|
page.<< "$('notes').value = \"#{escape_javascript content}\";" page.<< "$('notes').value = \"#{escape_javascript content}\";"
page.show 'update' page.show 'update'
@@ -78,7 +78,7 @@ class JournalsController < ApplicationController
page << "$('notes').scrollTop = $('notes').scrollHeight - $('notes').clientHeight;" page << "$('notes').scrollTop = $('notes').scrollHeight - $('notes').clientHeight;"
} }
end end
def edit def edit
(render_403; return false) unless @journal.editable_by?(User.current) (render_403; return false) unless @journal.editable_by?(User.current)
if request.post? if request.post?
@@ -93,15 +93,15 @@ class JournalsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html { format.html {
# TODO: implement non-JS journal update # TODO: implement non-JS journal update
render :nothing => true render :nothing => true
} }
format.js format.js
end end
end end
end end
private private
def find_journal def find_journal
@journal = Journal.find(params[:id]) @journal = Journal.find(params[:id])
@project = @journal.journalized.project @project = @journal.journalized.project
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -18,7 +18,7 @@
class LdapAuthSourcesController < AuthSourcesController class LdapAuthSourcesController < AuthSourcesController
protected protected
def auth_source_class def auth_source_class
AuthSourceLdap AuthSourceLdap
end end
+15 -18
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -28,10 +28,10 @@ class MembersController < ApplicationController
attrs = params[:member].dup attrs = params[:member].dup
if (user_ids = attrs.delete(:user_ids)) if (user_ids = attrs.delete(:user_ids))
user_ids.each do |user_id| user_ids.each do |user_id|
members << Member.new(:role_ids => params[:member][:role_ids], :user_id => user_id) members << Member.new(attrs.merge(:user_id => user_id))
end end
else else
members << Member.new(:role_ids => params[:member][:role_ids], :user_id => params[:member][:user_id]) members << Member.new(attrs)
end end
@project.members << members @project.members << members
end end
@@ -40,8 +40,8 @@ class MembersController < ApplicationController
format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project } format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
format.js { format.js {
render(:update) {|page| render(:update) {|page|
page.replace_html "tab-content-members", :partial => 'projects/settings/members' page.replace_html "tab-content-members", :partial => 'projects/settings/members'
page << 'hideOnLoad()' page << 'hideOnLoad()'
members.each {|member| page.visual_effect(:highlight, "member-#{member.id}") } members.each {|member| page.visual_effect(:highlight, "member-#{member.id}") }
@@ -58,20 +58,17 @@ class MembersController < ApplicationController
page.alert(l(:notice_failed_to_save_members, :errors => errors.join(', '))) page.alert(l(:notice_failed_to_save_members, :errors => errors.join(', ')))
} }
} }
end end
end end
end end
def edit def edit
if params[:member] if request.post? and @member.update_attributes(params[:member])
@member.role_ids = params[:member][:role_ids]
end
if request.post? and @member.save
respond_to do |format| respond_to do |format|
format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project } format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
format.js { format.js {
render(:update) {|page| render(:update) {|page|
page.replace_html "tab-content-members", :partial => 'projects/settings/members' page.replace_html "tab-content-members", :partial => 'projects/settings/members'
page << 'hideOnLoad()' page << 'hideOnLoad()'
page.visual_effect(:highlight, "member-#{@member.id}") page.visual_effect(:highlight, "member-#{@member.id}")
@@ -94,9 +91,9 @@ class MembersController < ApplicationController
} }
end end
end end
def autocomplete_for_member def autocomplete_for_member
@principals = Principal.active.not_member_of(@project).like(params[:q]).all(:limit => 100) @principals = Principal.active.like(params[:q]).find(:all, :limit => 100) - @project.principals
render :layout => false render :layout => false
end end
+26 -21
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -27,10 +27,10 @@ class MessagesController < ApplicationController
helper :watchers helper :watchers
helper :attachments helper :attachments
include AttachmentsHelper include AttachmentsHelper
REPLIES_PER_PAGE = 25 unless const_defined?(:REPLIES_PER_PAGE) REPLIES_PER_PAGE = 25 unless const_defined?(:REPLIES_PER_PAGE)
# Show a topic and its replies # Show a topic and its replies
def show def show
page = params[:page] page = params[:page]
@@ -39,24 +39,27 @@ class MessagesController < ApplicationController
offset = @topic.children.count(:conditions => ["#{Message.table_name}.id < ?", params[:r].to_i]) offset = @topic.children.count(:conditions => ["#{Message.table_name}.id < ?", params[:r].to_i])
page = 1 + offset / REPLIES_PER_PAGE page = 1 + offset / REPLIES_PER_PAGE
end end
@reply_count = @topic.children.count @reply_count = @topic.children.count
@reply_pages = Paginator.new self, @reply_count, REPLIES_PER_PAGE, page @reply_pages = Paginator.new self, @reply_count, REPLIES_PER_PAGE, page
@replies = @topic.children.find(:all, :include => [:author, :attachments, {:board => :project}], @replies = @topic.children.find(:all, :include => [:author, :attachments, {:board => :project}],
:order => "#{Message.table_name}.created_on ASC", :order => "#{Message.table_name}.created_on ASC",
:limit => @reply_pages.items_per_page, :limit => @reply_pages.items_per_page,
:offset => @reply_pages.current.offset) :offset => @reply_pages.current.offset)
@reply = Message.new(:subject => "RE: #{@message.subject}") @reply = Message.new(:subject => "RE: #{@message.subject}")
render :action => "show", :layout => false if request.xhr? render :action => "show", :layout => false if request.xhr?
end end
# Create a new topic # Create a new topic
def new def new
@message = Message.new @message = Message.new(params[:message])
@message.author = User.current @message.author = User.current
@message.board = @board @message.board = @board
@message.safe_attributes = params[:message] if params[:message] && User.current.allowed_to?(:edit_messages, @project)
@message.locked = params[:message]['locked']
@message.sticky = params[:message]['sticky']
end
if request.post? && @message.save if request.post? && @message.save
call_hook(:controller_messages_new_after_save, { :params => params, :message => @message}) call_hook(:controller_messages_new_after_save, { :params => params, :message => @message})
attachments = Attachment.attach_files(@message, params[:attachments]) attachments = Attachment.attach_files(@message, params[:attachments])
@@ -67,10 +70,9 @@ class MessagesController < ApplicationController
# Reply to a topic # Reply to a topic
def reply def reply
@reply = Message.new @reply = Message.new(params[:reply])
@reply.author = User.current @reply.author = User.current
@reply.board = @board @reply.board = @board
@reply.safe_attributes = params[:reply]
@topic.children << @reply @topic.children << @reply
if !@reply.new_record? if !@reply.new_record?
call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply}) call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply})
@@ -83,8 +85,11 @@ class MessagesController < ApplicationController
# Edit a message # Edit a message
def edit def edit
(render_403; return false) unless @message.editable_by?(User.current) (render_403; return false) unless @message.editable_by?(User.current)
@message.safe_attributes = params[:message] if params[:message]
if request.post? && @message.save @message.locked = params[:message]['locked']
@message.sticky = params[:message]['sticky']
end
if request.post? && @message.update_attributes(params[:message])
attachments = Attachment.attach_files(@message, params[:attachments]) attachments = Attachment.attach_files(@message, params[:attachments])
render_attachment_warning_if_needed(@message) render_attachment_warning_if_needed(@message)
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
@@ -92,7 +97,7 @@ class MessagesController < ApplicationController
redirect_to :action => 'show', :board_id => @message.board, :id => @message.root, :r => (@message.parent_id && @message.id) redirect_to :action => 'show', :board_id => @message.board, :id => @message.root, :r => (@message.parent_id && @message.id)
end end
end end
# Delete a messages # Delete a messages
def destroy def destroy
(render_403; return false) unless @message.destroyable_by?(User.current) (render_403; return false) unless @message.destroyable_by?(User.current)
@@ -101,7 +106,7 @@ class MessagesController < ApplicationController
{ :controller => 'boards', :action => 'show', :project_id => @project, :id => @board } : { :controller => 'boards', :action => 'show', :project_id => @project, :id => @board } :
{ :action => 'show', :id => @message.parent, :r => @message } { :action => 'show', :id => @message.parent, :r => @message }
end end
def quote def quote
user = @message.author user = @message.author
text = @message.content text = @message.content
@@ -110,7 +115,7 @@ class MessagesController < ApplicationController
content = "#{ll(Setting.default_language, :text_user_wrote, user)}\\n> " content = "#{ll(Setting.default_language, :text_user_wrote, user)}\\n> "
content << text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub('"', '\"').gsub(/(\r?\n|\r\n?)/, "\\n> ") + "\\n\\n" content << text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub('"', '\"').gsub(/(\r?\n|\r\n?)/, "\\n> ") + "\\n\\n"
render(:update) { |page| render(:update) { |page|
page << "$('message_subject').value = \"#{subject}\";" page << "$('reply_subject').value = \"#{subject}\";"
page.<< "$('message_content').value = \"#{content}\";" page.<< "$('message_content').value = \"#{content}\";"
page.show 'reply' page.show 'reply'
page << "Form.Element.focus('message_content');" page << "Form.Element.focus('message_content');"
@@ -118,14 +123,14 @@ class MessagesController < ApplicationController
page << "$('message_content').scrollTop = $('message_content').scrollHeight - $('message_content').clientHeight;" page << "$('message_content').scrollTop = $('message_content').scrollHeight - $('message_content').clientHeight;"
} }
end end
def preview def preview
message = @board.messages.find_by_id(params[:id]) message = @board.messages.find_by_id(params[:id])
@attachements = message.attachments if message @attachements = message.attachments if message
@text = (params[:message] || params[:reply])[:content] @text = (params[:message] || params[:reply])[:content]
render :partial => 'common/preview' render :partial => 'common/preview'
end end
private private
def find_message def find_message
find_board find_board
@@ -134,7 +139,7 @@ private
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
def find_board def find_board
@board = Board.find(params[:board_id], :include => :project) @board = Board.find(params[:board_id], :include => :project)
@project = @board.project @project = @board.project
+11 -11
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2009 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -31,8 +31,8 @@ class MyController < ApplicationController
'timelog' => :label_spent_time 'timelog' => :label_spent_time
}.merge(Redmine::Views::MyPage::Block.additional_blocks).freeze }.merge(Redmine::Views::MyPage::Block.additional_blocks).freeze
DEFAULT_LAYOUT = { 'left' => ['issuesassignedtome'], DEFAULT_LAYOUT = { 'left' => ['issuesassignedtome'],
'right' => ['issuesreportedbyme'] 'right' => ['issuesreportedbyme']
}.freeze }.freeze
verify :xhr => true, verify :xhr => true,
@@ -88,7 +88,7 @@ class MyController < ApplicationController
end end
end end
end end
# Create a new feeds key # Create a new feeds key
def reset_rss_key def reset_rss_key
if request.post? if request.post?
@@ -122,7 +122,7 @@ class MyController < ApplicationController
@block_options = [] @block_options = []
BLOCKS.each {|k, v| @block_options << [l("my.blocks.#{v}", :default => [v, v.to_s.humanize]), k.dasherize]} BLOCKS.each {|k, v| @block_options << [l("my.blocks.#{v}", :default => [v, v.to_s.humanize]), k.dasherize]}
end end
# Add a block to user's page # Add a block to user's page
# The block is added on top of the page # The block is added on top of the page
# params[:block] : id of the block to add # params[:block] : id of the block to add
@@ -136,10 +136,10 @@ class MyController < ApplicationController
# add it on top # add it on top
layout['top'].unshift block layout['top'].unshift block
@user.pref[:my_page_layout] = layout @user.pref[:my_page_layout] = layout
@user.pref.save @user.pref.save
render :partial => "block", :locals => {:user => @user, :block_name => block} render :partial => "block", :locals => {:user => @user, :block_name => block}
end end
# Remove a block to user's page # Remove a block to user's page
# params[:block] : id of the block to remove # params[:block] : id of the block to remove
def remove_block def remove_block
@@ -149,7 +149,7 @@ class MyController < ApplicationController
layout = @user.pref[:my_page_layout] || {} layout = @user.pref[:my_page_layout] || {}
%w(top left right).each {|f| (layout[f] ||= []).delete block } %w(top left right).each {|f| (layout[f] ||= []).delete block }
@user.pref[:my_page_layout] = layout @user.pref[:my_page_layout] = layout
@user.pref.save @user.pref.save
render :nothing => true render :nothing => true
end end
@@ -169,7 +169,7 @@ class MyController < ApplicationController
} }
layout[group] = group_items layout[group] = group_items
@user.pref[:my_page_layout] = layout @user.pref[:my_page_layout] = layout
@user.pref.save @user.pref.save
end end
end end
render :nothing => true render :nothing => true
+14 -18
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -25,9 +25,9 @@ class NewsController < ApplicationController
before_filter :find_optional_project, :only => :index before_filter :find_optional_project, :only => :index
accept_rss_auth :index accept_rss_auth :index
accept_api_auth :index accept_api_auth :index
helper :watchers helper :watchers
def index def index
case params[:format] case params[:format]
when 'xml', 'json' when 'xml', 'json'
@@ -35,9 +35,9 @@ class NewsController < ApplicationController
else else
@limit = 10 @limit = 10
end end
scope = @project ? @project.news.visible : News.visible scope = @project ? @project.news.visible : News.visible
@news_count = scope.count @news_count = scope.count
@news_pages = Paginator.new self, @news_count, @limit, params['page'] @news_pages = Paginator.new self, @news_count, @limit, params['page']
@offset ||= @news_pages.current.offset @offset ||= @news_pages.current.offset
@@ -45,17 +45,14 @@ class NewsController < ApplicationController
:order => "#{News.table_name}.created_on DESC", :order => "#{News.table_name}.created_on DESC",
:offset => @offset, :offset => @offset,
:limit => @limit) :limit => @limit)
respond_to do |format| respond_to do |format|
format.html { format.html { render :layout => false if request.xhr? }
@news = News.new # for adding news inline
render :layout => false if request.xhr?
}
format.api format.api
format.atom { render_feed(@newss, :title => (@project ? @project.name : Setting.app_title) + ": #{l(:label_news_plural)}") } format.atom { render_feed(@newss, :title => (@project ? @project.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
end end
end end
def show def show
@comments = @news.comments @comments = @news.comments
@comments.reverse! if User.current.wants_comments_in_reverse_order? @comments.reverse! if User.current.wants_comments_in_reverse_order?
@@ -67,8 +64,8 @@ class NewsController < ApplicationController
def create def create
@news = News.new(:project => @project, :author => User.current) @news = News.new(:project => @project, :author => User.current)
@news.safe_attributes = params[:news]
if request.post? if request.post?
@news.attributes = params[:news]
if @news.save if @news.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'news', :action => 'index', :project_id => @project redirect_to :controller => 'news', :action => 'index', :project_id => @project
@@ -80,10 +77,9 @@ class NewsController < ApplicationController
def edit def edit
end end
def update def update
@news.safe_attributes = params[:news] if request.put? and @news.update_attributes(params[:news])
if request.put? and @news.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'show', :id => @news redirect_to :action => 'show', :id => @news
else else
@@ -95,14 +91,14 @@ class NewsController < ApplicationController
@news.destroy @news.destroy
redirect_to :action => 'index', :project_id => @project redirect_to :action => 'index', :project_id => @project
end end
private private
def find_project def find_project
@project = Project.find(params[:project_id]) @project = Project.find(params[:project_id])
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
def find_optional_project def find_optional_project
return true unless params[:project_id] return true unless params[:project_id]
@project = Project.find(params[:project_id]) @project = Project.find(params[:project_id])
+4 -4
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -39,12 +39,12 @@ class PreviewsController < ApplicationController
end end
private private
def find_project def find_project
project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id] project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
@project = Project.find(project_id) @project = Project.find(project_id)
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
end end
@@ -1,7 +1,7 @@
class ProjectEnumerationsController < ApplicationController class ProjectEnumerationsController < ApplicationController
before_filter :find_project_by_project_id before_filter :find_project_by_project_id
before_filter :authorize before_filter :authorize
def update def update
if request.put? && params[:enumerations] if request.put? && params[:enumerations]
Project.transaction do Project.transaction do
@@ -11,7 +11,7 @@ class ProjectEnumerationsController < ApplicationController
end end
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
end end
redirect_to :controller => 'projects', :action => 'settings', :tab => 'activities', :id => @project redirect_to :controller => 'projects', :action => 'settings', :tab => 'activities', :id => @project
end end
+25 -29
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -19,7 +19,7 @@ class ProjectsController < ApplicationController
menu_item :overview menu_item :overview
menu_item :roadmap, :only => :roadmap menu_item :roadmap, :only => :roadmap
menu_item :settings, :only => :settings menu_item :settings, :only => :settings
before_filter :find_project, :except => [ :index, :list, :new, :create, :copy ] before_filter :find_project, :except => [ :index, :list, :new, :create, :copy ]
before_filter :authorize, :except => [ :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy] before_filter :authorize, :except => [ :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy]
before_filter :authorize_global, :only => [:new, :create] before_filter :authorize_global, :only => [:new, :create]
@@ -36,19 +36,19 @@ class ProjectsController < ApplicationController
helper :sort helper :sort
include SortHelper include SortHelper
helper :custom_fields helper :custom_fields
include CustomFieldsHelper include CustomFieldsHelper
helper :issues helper :issues
helper :queries helper :queries
include QueriesHelper include QueriesHelper
helper :repositories helper :repositories
include RepositoriesHelper include RepositoriesHelper
include ProjectsHelper include ProjectsHelper
# Lists visible projects # Lists visible projects
def index def index
respond_to do |format| respond_to do |format|
format.html { format.html {
@projects = Project.visible.find(:all, :order => 'lft') @projects = Project.visible.find(:all, :order => 'lft')
} }
format.api { format.api {
@offset, @limit = api_offset_and_limit @offset, @limit = api_offset_and_limit
@@ -62,12 +62,11 @@ class ProjectsController < ApplicationController
} }
end end
end end
def new def new
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position") @issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
@trackers = Tracker.all @trackers = Tracker.all
@project = Project.new @project = Project.new(params[:project])
@project.safe_attributes = params[:project]
end end
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
@@ -86,12 +85,9 @@ class ProjectsController < ApplicationController
@project.members << m @project.members << m
end end
respond_to do |format| respond_to do |format|
format.html { format.html {
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to(params[:continue] ? redirect_to :controller => 'projects', :action => 'settings', :id => @project
{:controller => 'projects', :action => 'new', :project => {:parent_id => @project.parent_id}.reject {|k,v| v.nil?}} :
{:controller => 'projects', :action => 'settings', :id => @project}
)
} }
format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) } format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
end end
@@ -101,9 +97,9 @@ class ProjectsController < ApplicationController
format.api { render_validation_errors(@project) } format.api { render_validation_errors(@project) }
end end
end end
end end
def copy def copy
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position") @issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
@trackers = Tracker.all @trackers = Tracker.all
@@ -117,7 +113,7 @@ class ProjectsController < ApplicationController
@project.identifier = Project.next_identifier if Setting.sequential_project_identifiers? @project.identifier = Project.next_identifier if Setting.sequential_project_identifiers?
else else
redirect_to :controller => 'admin', :action => 'projects' redirect_to :controller => 'admin', :action => 'projects'
end end
else else
Mailer.with_deliveries(params[:notifications] == '1') do Mailer.with_deliveries(params[:notifications] == '1') do
@project = Project.new @project = Project.new
@@ -145,27 +141,27 @@ class ProjectsController < ApplicationController
# try to redirect to the requested menu item # try to redirect to the requested menu item
redirect_to_project_menu_item(@project, params[:jump]) && return redirect_to_project_menu_item(@project, params[:jump]) && return
end end
@users_by_role = @project.users_by_role @users_by_role = @project.users_by_role
@subprojects = @project.children.visible.all @subprojects = @project.children.visible.all
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC") @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
@trackers = @project.rolled_up_trackers @trackers = @project.rolled_up_trackers
cond = @project.project_condition(Setting.display_subprojects_issues?) cond = @project.project_condition(Setting.display_subprojects_issues?)
@open_issues_by_tracker = Issue.visible.count(:group => :tracker, @open_issues_by_tracker = Issue.visible.count(:group => :tracker,
:include => [:project, :status, :tracker], :include => [:project, :status, :tracker],
:conditions => ["(#{cond}) AND #{IssueStatus.table_name}.is_closed=?", false]) :conditions => ["(#{cond}) AND #{IssueStatus.table_name}.is_closed=?", false])
@total_issues_by_tracker = Issue.visible.count(:group => :tracker, @total_issues_by_tracker = Issue.visible.count(:group => :tracker,
:include => [:project, :status, :tracker], :include => [:project, :status, :tracker],
:conditions => cond) :conditions => cond)
if User.current.allowed_to?(:view_time_entries, @project) if User.current.allowed_to?(:view_time_entries, @project)
@total_hours = TimeEntry.visible.sum(:hours, :include => :project, :conditions => cond).to_f @total_hours = TimeEntry.visible.sum(:hours, :include => :project, :conditions => cond).to_f
end end
@key = User.current.rss_key @key = User.current.rss_key
respond_to do |format| respond_to do |format|
format.html format.html
format.api format.api
@@ -180,7 +176,7 @@ class ProjectsController < ApplicationController
@repository ||= @project.repository @repository ||= @project.repository
@wiki ||= @project.wiki @wiki ||= @project.wiki
end end
def edit def edit
end end
@@ -191,7 +187,7 @@ class ProjectsController < ApplicationController
if validate_parent_id && @project.save if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id') @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
respond_to do |format| respond_to do |format|
format.html { format.html {
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'settings', :id => @project redirect_to :action => 'settings', :id => @project
} }
@@ -199,7 +195,7 @@ class ProjectsController < ApplicationController
end end
else else
respond_to do |format| respond_to do |format|
format.html { format.html {
settings settings
render :action => 'settings' render :action => 'settings'
} }
@@ -223,12 +219,12 @@ class ProjectsController < ApplicationController
end end
redirect_to(url_for(:controller => 'admin', :action => 'projects', :status => params[:status])) redirect_to(url_for(:controller => 'admin', :action => 'projects', :status => params[:status]))
end end
def unarchive def unarchive
@project.unarchive if request.post? && !@project.active? @project.unarchive if request.post? && !@project.active?
redirect_to(url_for(:controller => 'admin', :action => 'projects', :status => params[:status])) redirect_to(url_for(:controller => 'admin', :action => 'projects', :status => params[:status]))
end end
# Delete @project # Delete @project
def destroy def destroy
@project_to_destroy = @project @project_to_destroy = @project
+34 -64
View File
@@ -1,97 +1,67 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class QueriesController < ApplicationController class QueriesController < ApplicationController
menu_item :issues menu_item :issues
before_filter :find_query, :except => [:new, :create, :index] before_filter :find_query, :except => :new
before_filter :find_optional_project, :only => [:new, :create] before_filter :find_optional_project, :only => :new
accept_api_auth :index
include QueriesHelper
def index
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit
else
@limit = per_page_option
end
@query_count = Query.visible.count
@query_pages = Paginator.new self, @query_count, @limit, params['page']
@queries = Query.visible.all(:limit => @limit, :offset => @offset, :order => "#{Query.table_name}.name")
respond_to do |format|
format.html { render :nothing => true }
format.api
end
end
def new def new
@query = Query.new
@query.user = User.current
@query.project = @project
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
build_query_from_params
end
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create
@query = Query.new(params[:query]) @query = Query.new(params[:query])
@query.user = User.current
@query.project = params[:query_is_for_all] ? nil : @project @query.project = params[:query_is_for_all] ? nil : @project
@query.user = User.current
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin? @query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
build_query_from_params
@query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f]
@query.group_by ||= params[:group_by]
@query.column_names = params[:c] if params[:c]
@query.column_names = nil if params[:default_columns] @query.column_names = nil if params[:default_columns]
if @query.save if request.post? && params[:confirm] && @query.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :query_id => @query redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :query_id => @query
else return
render :action => 'new', :layout => !request.xhr?
end end
render :layout => false if request.xhr?
end end
def edit def edit
end if request.post?
@query.filters = {}
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } @query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) if params[:fields] || params[:f]
def update @query.attributes = params[:query]
@query.attributes = params[:query] @query.project = nil if params[:query_is_for_all]
@query.project = nil if params[:query_is_for_all] @query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin? @query.group_by ||= params[:group_by]
build_query_from_params @query.column_names = params[:c] if params[:c]
@query.column_names = nil if params[:default_columns] @query.column_names = nil if params[:default_columns]
if @query.save if @query.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :query_id => @query redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :query_id => @query
else end
render :action => 'edit'
end end
end end
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
def destroy def destroy
@query.destroy @query.destroy if request.post?
redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1 redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1
end end
private private
def find_query def find_query
@query = Query.find(params[:id]) @query = Query.find(params[:id])
@@ -100,7 +70,7 @@ private
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
def find_optional_project def find_optional_project
@project = Project.find(params[:project_id]) if params[:project_id] @project = Project.find(params[:project_id]) if params[:project_id]
render_403 unless User.current.allowed_to?(:save_queries, @project, :global => true) render_403 unless User.current.allowed_to?(:save_queries, @project, :global => true)
+9 -9
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -24,8 +24,8 @@ class ReportsController < ApplicationController
@versions = @project.shared_versions.sort @versions = @project.shared_versions.sort
@priorities = IssuePriority.all @priorities = IssuePriority.all
@categories = @project.issue_categories @categories = @project.issue_categories
@assignees = (Setting.issue_group_assignment? ? @project.principals : @project.users).sort @assignees = @project.members.collect { |m| m.user }.sort
@authors = @project.users.sort @authors = @project.members.collect { |m| m.user }.sort
@subprojects = @project.descendants.visible @subprojects = @project.descendants.visible
@issues_by_tracker = Issue.by_tracker(@project) @issues_by_tracker = Issue.by_tracker(@project)
@@ -37,7 +37,7 @@ class ReportsController < ApplicationController
@issues_by_subproject = Issue.by_subproject(@project) || [] @issues_by_subproject = Issue.by_subproject(@project) || []
render :template => "reports/issue_report" render :template => "reports/issue_report"
end end
def issue_report_details def issue_report_details
case params[:detail] case params[:detail]
@@ -63,12 +63,12 @@ class ReportsController < ApplicationController
@report_title = l(:field_category) @report_title = l(:field_category)
when "assigned_to" when "assigned_to"
@field = "assigned_to_id" @field = "assigned_to_id"
@rows = (Setting.issue_group_assignment? ? @project.principals : @project.users).sort @rows = @project.members.collect { |m| m.user }.sort
@data = Issue.by_assigned_to(@project) @data = Issue.by_assigned_to(@project)
@report_title = l(:field_assigned_to) @report_title = l(:field_assigned_to)
when "author" when "author"
@field = "author_id" @field = "author_id"
@rows = @project.users.sort @rows = @project.members.collect { |m| m.user }.sort
@data = Issue.by_author(@project) @data = Issue.by_author(@project)
@report_title = l(:field_author) @report_title = l(:field_author)
when "subproject" when "subproject"
+4 -13
View File
@@ -121,7 +121,7 @@ class RepositoriesController < ApplicationController
@changesets = @repository.changesets.find(:all, @changesets = @repository.changesets.find(:all,
:limit => @changeset_pages.items_per_page, :limit => @changeset_pages.items_per_page,
:offset => @changeset_pages.current.offset, :offset => @changeset_pages.current.offset,
:include => [:user, :repository, :parents]) :include => [:user, :repository])
respond_to do |format| respond_to do |format|
format.html { render :layout => false if request.xhr? } format.html { render :layout => false if request.xhr? }
@@ -172,16 +172,7 @@ class RepositoriesController < ApplicationController
(show_error_not_found; return) unless @entry (show_error_not_found; return) unless @entry
@annotate = @repository.scm.annotate(@path, @rev) @annotate = @repository.scm.annotate(@path, @rev)
if @annotate.nil? || @annotate.empty? (render_error l(:error_scm_annotate); return) if @annotate.nil? || @annotate.empty?
(render_error l(:error_scm_annotate); return)
end
ann_buf_size = 0
@annotate.lines.each do |buf|
ann_buf_size += buf.size
end
if ann_buf_size > Setting.file_max_size_displayed.to_i.kilobyte
(render_error l(:error_scm_annotate_big_text_file); return)
end
@changeset = @repository.find_changeset_by_name(@rev) @changeset = @repository.find_changeset_by_name(@rev)
end end
@@ -216,7 +207,7 @@ class RepositoriesController < ApplicationController
User.current.pref[:diff_type] = @diff_type User.current.pref[:diff_type] = @diff_type
User.current.preference.save User.current.preference.save
end end
@cache_key = "repositories/diff/#{@repository.id}/" + @cache_key = "repositories/diff/#{@repository.id}/" +
Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}") Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}-#{current_language}")
unless read_fragment(@cache_key) unless read_fragment(@cache_key)
@diff = @repository.diff(@path, @rev, @rev_to) @diff = @repository.diff(@path, @rev, @rev_to)
@@ -258,7 +249,7 @@ class RepositoriesController < ApplicationController
(render_404; return false) unless @repository (render_404; return false) unless @repository
@path = params[:path].join('/') unless params[:path].nil? @path = params[:path].join('/') unless params[:path].nil?
@path ||= '' @path ||= ''
@rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].strip
@rev_to = params[:rev_to] @rev_to = params[:rev_to]
unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE) unless @rev.to_s.match(REV_PARAM_RE) && @rev_to.to_s.match(REV_PARAM_RE)
+9 -9
View File
@@ -1,26 +1,26 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class RolesController < ApplicationController class RolesController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin before_filter :require_admin
verify :method => :post, :only => [ :destroy ], verify :method => :post, :only => [ :destroy, :move ],
:redirect_to => { :action => :index } :redirect_to => { :action => :index }
def index def index
@@ -50,7 +50,7 @@ class RolesController < ApplicationController
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'index' redirect_to :action => 'index'
else else
@permissions = @role.setable_permissions @permissions = @role.setable_permissions
end end
end end
@@ -62,8 +62,8 @@ class RolesController < ApplicationController
flash[:error] = l(:error_can_not_remove_role) flash[:error] = l(:error_can_not_remove_role)
redirect_to :action => 'index' redirect_to :action => 'index'
end end
def report def report
@roles = Role.find(:all, :order => 'builtin, position') @roles = Role.find(:all, :order => 'builtin, position')
@permissions = Redmine::AccessControl.permissions.select { |p| !p.public? } @permissions = Redmine::AccessControl.permissions.select { |p| !p.public? }
if request.post? if request.post?
+15 -15
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -26,7 +26,7 @@ class SearchController < ApplicationController
@question.strip! @question.strip!
@all_words = params[:all_words] ? params[:all_words].present? : true @all_words = params[:all_words] ? params[:all_words].present? : true
@titles_only = params[:titles_only] ? params[:titles_only].present? : false @titles_only = params[:titles_only] ? params[:titles_only].present? : false
projects_to_search = projects_to_search =
case params[:scope] case params[:scope]
when 'all' when 'all'
@@ -38,16 +38,16 @@ class SearchController < ApplicationController
else else
@project @project
end end
offset = nil offset = nil
begin; offset = params[:offset].to_time if params[:offset]; rescue; end begin; offset = params[:offset].to_time if params[:offset]; rescue; end
# quick jump to an issue # quick jump to an issue
if @question.match(/^#?(\d+)$/) && Issue.visible.find_by_id($1.to_i) if @question.match(/^#?(\d+)$/) && Issue.visible.find_by_id($1.to_i)
redirect_to :controller => "issues", :action => "show", :id => $1 redirect_to :controller => "issues", :action => "show", :id => $1
return return
end end
@object_types = Redmine::Search.available_search_types.dup @object_types = Redmine::Search.available_search_types.dup
if projects_to_search.is_a? Project if projects_to_search.is_a? Project
# don't search projects # don't search projects
@@ -55,23 +55,23 @@ class SearchController < ApplicationController
# only show what the user is allowed to view # only show what the user is allowed to view
@object_types = @object_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, projects_to_search)} @object_types = @object_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, projects_to_search)}
end end
@scope = @object_types.select {|t| params[t]} @scope = @object_types.select {|t| params[t]}
@scope = @object_types if @scope.empty? @scope = @object_types if @scope.empty?
# extract tokens from the question # extract tokens from the question
# eg. hello "bye bye" => ["hello", "bye bye"] # eg. hello "bye bye" => ["hello", "bye bye"]
@tokens = @question.scan(%r{((\s|^)"[\s\w]+"(\s|$)|\S+)}).collect {|m| m.first.gsub(%r{(^\s*"\s*|\s*"\s*$)}, '')} @tokens = @question.scan(%r{((\s|^)"[\s\w]+"(\s|$)|\S+)}).collect {|m| m.first.gsub(%r{(^\s*"\s*|\s*"\s*$)}, '')}
# tokens must be at least 2 characters long # tokens must be at least 2 characters long
@tokens = @tokens.uniq.select {|w| w.length > 1 } @tokens = @tokens.uniq.select {|w| w.length > 1 }
if !@tokens.empty? if !@tokens.empty?
# no more than 5 tokens to search for # no more than 5 tokens to search for
@tokens.slice! 5..-1 if @tokens.size > 5 @tokens.slice! 5..-1 if @tokens.size > 5
@results = [] @results = []
@results_by_type = Hash.new {|h,k| h[k] = 0} @results_by_type = Hash.new {|h,k| h[k] = 0}
limit = 10 limit = 10
@scope.each do |s| @scope.each do |s|
r, c = s.singularize.camelcase.constantize.search(@tokens, projects_to_search, r, c = s.singularize.camelcase.constantize.search(@tokens, projects_to_search,
@@ -87,13 +87,13 @@ class SearchController < ApplicationController
if params[:previous].nil? if params[:previous].nil?
@pagination_previous_date = @results[0].event_datetime if offset && @results[0] @pagination_previous_date = @results[0].event_datetime if offset && @results[0]
if @results.size > limit if @results.size > limit
@pagination_next_date = @results[limit-1].event_datetime @pagination_next_date = @results[limit-1].event_datetime
@results = @results[0, limit] @results = @results[0, limit]
end end
else else
@pagination_next_date = @results[-1].event_datetime if offset && @results[-1] @pagination_next_date = @results[-1].event_datetime if offset && @results[-1]
if @results.size > limit if @results.size > limit
@pagination_previous_date = @results[-(limit)].event_datetime @pagination_previous_date = @results[-(limit)].event_datetime
@results = @results[-(limit), limit] @results = @results[-(limit), limit]
end end
end end
@@ -103,7 +103,7 @@ class SearchController < ApplicationController
render :layout => false if request.xhr? render :layout => false if request.xhr?
end end
private private
def find_optional_project def find_optional_project
return true unless params[:id] return true unless params[:id]
@project = Project.find(params[:id]) @project = Project.find(params[:id])
+6 -6
View File
@@ -1,29 +1,29 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2009 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class SysController < ActionController::Base class SysController < ActionController::Base
before_filter :check_enabled before_filter :check_enabled
def projects def projects
p = Project.active.has_module(:repository).find(:all, :include => :repository, :order => 'identifier') p = Project.active.has_module(:repository).find(:all, :include => :repository, :order => 'identifier')
# extra_info attribute from repository breaks activeresource client # extra_info attribute from repository breaks activeresource client
render :xml => p.to_xml(:only => [:id, :identifier, :name, :is_public, :status], :include => {:repository => {:only => [:id, :url]}}) render :xml => p.to_xml(:only => [:id, :identifier, :name, :is_public, :status], :include => {:repository => {:only => [:id, :url]}})
end end
def create_project_repository def create_project_repository
project = Project.find(params[:id]) project = Project.find(params[:id])
if project.repository if project.repository
@@ -38,7 +38,7 @@ class SysController < ActionController::Base
end end
end end
end end
def fetch_changesets def fetch_changesets
projects = [] projects = []
if params[:id] if params[:id]
@@ -16,16 +16,16 @@ class TimeEntryReportsController < ApplicationController
@criterias = @criterias.select{|criteria| @available_criterias.has_key? criteria} @criterias = @criterias.select{|criteria| @available_criterias.has_key? criteria}
@criterias.uniq! @criterias.uniq!
@criterias = @criterias[0,3] @criterias = @criterias[0,3]
@columns = (params[:columns] && %w(year month week day).include?(params[:columns])) ? params[:columns] : 'month' @columns = (params[:columns] && %w(year month week day).include?(params[:columns])) ? params[:columns] : 'month'
retrieve_date_range retrieve_date_range
unless @criterias.empty? unless @criterias.empty?
sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ') sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ')
sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ') sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ')
sql_condition = '' sql_condition = ''
if @project.nil? if @project.nil?
sql_condition = Project.allowed_to_condition(User.current, :view_time_entries) sql_condition = Project.allowed_to_condition(User.current, :view_time_entries)
elsif @issue.nil? elsif @issue.nil?
@@ -41,9 +41,9 @@ class TimeEntryReportsController < ApplicationController
sql << " (%s) AND" % sql_condition sql << " (%s) AND" % sql_condition
sql << " (spent_on BETWEEN '%s' AND '%s')" % [ActiveRecord::Base.connection.quoted_date(@from), ActiveRecord::Base.connection.quoted_date(@to)] sql << " (spent_on BETWEEN '%s' AND '%s')" % [ActiveRecord::Base.connection.quoted_date(@from), ActiveRecord::Base.connection.quoted_date(@to)]
sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on" sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on"
@hours = ActiveRecord::Base.connection.select_all(sql) @hours = ActiveRecord::Base.connection.select_all(sql)
@hours.each do |row| @hours.each do |row|
case @columns case @columns
when 'year' when 'year'
@@ -56,9 +56,9 @@ class TimeEntryReportsController < ApplicationController
row['day'] = "#{row['spent_on']}" row['day'] = "#{row['spent_on']}"
end end
end end
@total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f} @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f}
@periods = [] @periods = []
# Date#at_beginning_of_ not supported in Rails 1.2.x # Date#at_beginning_of_ not supported in Rails 1.2.x
date_from = @from.to_time date_from = @from.to_time
@@ -80,13 +80,13 @@ class TimeEntryReportsController < ApplicationController
end end
end end
end end
respond_to do |format| respond_to do |format|
format.html { render :layout => !request.xhr? } format.html { render :layout => !request.xhr? }
format.csv { send_data(report_to_csv(@criterias, @periods, @hours), :type => 'text/csv; header=present', :filename => 'timelog.csv') } format.csv { send_data(report_to_csv(@criterias, @periods, @hours), :type => 'text/csv; header=present', :filename => 'timelog.csv') }
end end
end end
private private
# TODO: duplicated in TimelogController # TODO: duplicated in TimelogController
@@ -141,7 +141,7 @@ class TimeEntryReportsController < ApplicationController
else else
# default # default
end end
@from, @to = @to, @from if @from && @to && @from > @to @from, @to = @to, @from if @from && @to && @from > @to
@from ||= (TimeEntry.earilest_date_for_project(@project) || Date.today) @from ||= (TimeEntry.earilest_date_for_project(@project) || Date.today)
@to ||= (TimeEntry.latest_date_for_project(@project) || Date.today) @to ||= (TimeEntry.latest_date_for_project(@project) || Date.today)
@@ -170,7 +170,7 @@ class TimeEntryReportsController < ApplicationController
:klass => Issue, :klass => Issue,
:label => :label_issue} :label => :label_issue}
} }
# Add list and boolean custom fields as available criterias # Add list and boolean custom fields as available criterias
custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields) custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields)
custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf| custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
@@ -178,7 +178,7 @@ class TimeEntryReportsController < ApplicationController
:format => cf.field_format, :format => cf.field_format,
:label => cf.name} :label => cf.name}
end if @project end if @project
# Add list and boolean time entry custom fields # Add list and boolean time entry custom fields
TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
@available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id)", @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id)",
+28 -28
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -24,14 +24,14 @@ class TimelogController < ApplicationController
before_filter :find_optional_project, :only => [:index] before_filter :find_optional_project, :only => [:index]
accept_rss_auth :index accept_rss_auth :index
accept_api_auth :index, :show, :create, :update, :destroy accept_api_auth :index, :show, :create, :update, :destroy
helper :sort helper :sort
include SortHelper include SortHelper
helper :issues helper :issues
include TimelogHelper include TimelogHelper
helper :custom_fields helper :custom_fields
include CustomFieldsHelper include CustomFieldsHelper
def index def index
sort_init 'spent_on', 'desc' sort_init 'spent_on', 'desc'
sort_update 'spent_on' => 'spent_on', sort_update 'spent_on' => 'spent_on',
@@ -40,14 +40,14 @@ class TimelogController < ApplicationController
'project' => "#{Project.table_name}.name", 'project' => "#{Project.table_name}.name",
'issue' => 'issue_id', 'issue' => 'issue_id',
'hours' => 'hours' 'hours' => 'hours'
cond = ARCondition.new cond = ARCondition.new
if @issue if @issue
cond << "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}" cond << "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}"
elsif @project elsif @project
cond << @project.project_condition(Setting.display_subprojects_issues?) cond << @project.project_condition(Setting.display_subprojects_issues?)
end end
retrieve_date_range retrieve_date_range
cond << ['spent_on BETWEEN ? AND ?', @from, @to] cond << ['spent_on BETWEEN ? AND ?', @from, @to]
@@ -56,7 +56,7 @@ class TimelogController < ApplicationController
# Paginate results # Paginate results
@entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions) @entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions)
@entry_pages = Paginator.new self, @entry_count, per_page_option, params['page'] @entry_pages = Paginator.new self, @entry_count, per_page_option, params['page']
@entries = TimeEntry.visible.find(:all, @entries = TimeEntry.visible.find(:all,
:include => [:project, :activity, :user, {:issue => :tracker}], :include => [:project, :activity, :user, {:issue => :tracker}],
:conditions => cond.conditions, :conditions => cond.conditions,
:order => sort_clause, :order => sort_clause,
@@ -69,7 +69,7 @@ class TimelogController < ApplicationController
format.api { format.api {
@entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions) @entry_count = TimeEntry.visible.count(:include => [:project, :issue], :conditions => cond.conditions)
@offset, @limit = api_offset_and_limit @offset, @limit = api_offset_and_limit
@entries = TimeEntry.visible.find(:all, @entries = TimeEntry.visible.find(:all,
:include => [:project, :activity, :user, {:issue => :tracker}], :include => [:project, :activity, :user, {:issue => :tracker}],
:conditions => cond.conditions, :conditions => cond.conditions,
:order => sort_clause, :order => sort_clause,
@@ -86,7 +86,7 @@ class TimelogController < ApplicationController
} }
format.csv { format.csv {
# Export all entries # Export all entries
@entries = TimeEntry.visible.find(:all, @entries = TimeEntry.visible.find(:all,
:include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}], :include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
:conditions => cond.conditions, :conditions => cond.conditions,
:order => sort_clause) :order => sort_clause)
@@ -94,7 +94,7 @@ class TimelogController < ApplicationController
} }
end end
end end
def show def show
respond_to do |format| respond_to do |format|
# TODO: Implement html response # TODO: Implement html response
@@ -105,8 +105,8 @@ class TimelogController < ApplicationController
def new def new
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today) @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
@time_entry.safe_attributes = params[:time_entry] @time_entry.attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
render :action => 'edit' render :action => 'edit'
end end
@@ -114,10 +114,10 @@ class TimelogController < ApplicationController
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create def create
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today) @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
@time_entry.safe_attributes = params[:time_entry] @time_entry.attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if @time_entry.save if @time_entry.save
respond_to do |format| respond_to do |format|
format.html { format.html {
@@ -131,21 +131,21 @@ class TimelogController < ApplicationController
format.html { render :action => 'edit' } format.html { render :action => 'edit' }
format.api { render_validation_errors(@time_entry) } format.api { render_validation_errors(@time_entry) }
end end
end end
end end
def edit def edit
@time_entry.safe_attributes = params[:time_entry] @time_entry.attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
end end
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
def update def update
@time_entry.safe_attributes = params[:time_entry] @time_entry.attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if @time_entry.save if @time_entry.save
respond_to do |format| respond_to do |format|
format.html { format.html {
@@ -159,7 +159,7 @@ class TimelogController < ApplicationController
format.html { render :action => 'edit' } format.html { render :action => 'edit' }
format.api { render_validation_errors(@time_entry) } format.api { render_validation_errors(@time_entry) }
end end
end end
end end
def bulk_edit def bulk_edit
@@ -173,7 +173,7 @@ class TimelogController < ApplicationController
unsaved_time_entry_ids = [] unsaved_time_entry_ids = []
@time_entries.each do |time_entry| @time_entries.each do |time_entry|
time_entry.reload time_entry.reload
time_entry.safe_attributes = attributes time_entry.attributes = attributes
call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry }) call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry })
unless time_entry.save unless time_entry.save
# Keep unsaved time_entry ids to display them in flash error # Keep unsaved time_entry ids to display them in flash error
@@ -186,7 +186,7 @@ class TimelogController < ApplicationController
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
def destroy def destroy
@time_entries.each do |t| @time_entries.each do |t|
begin begin
unless t.destroy && t.destroyed? unless t.destroy && t.destroyed?
respond_to do |format| respond_to do |format|
@@ -258,7 +258,7 @@ private
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
def find_optional_project def find_optional_project
if !params[:issue_id].blank? if !params[:issue_id].blank?
@issue = Issue.find(params[:issue_id]) @issue = Issue.find(params[:issue_id])
@@ -268,7 +268,7 @@ private
end end
deny_access unless User.current.allowed_to?(:view_time_entries, @project, :global => true) deny_access unless User.current.allowed_to?(:view_time_entries, @project, :global => true)
end end
# Retrieves the date range based on predefined ranges or specific from/to param dates # Retrieves the date range based on predefined ranges or specific from/to param dates
def retrieve_date_range def retrieve_date_range
@free_period = false @free_period = false
@@ -309,7 +309,7 @@ private
else else
# default # default
end end
@from, @to = @to, @from if @from && @to && @from > @to @from, @to = @to, @from if @from && @to && @from > @to
@from ||= (TimeEntry.earilest_date_for_project(@project) || Date.today) @from ||= (TimeEntry.earilest_date_for_project(@project) || Date.today)
@to ||= (TimeEntry.latest_date_for_project(@project) || Date.today) @to ||= (TimeEntry.latest_date_for_project(@project) || Date.today)
+14 -34
View File
@@ -1,46 +1,33 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2009 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class TrackersController < ApplicationController class TrackersController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin
before_filter :require_admin, :except => :index verify :method => :post, :only => :destroy, :redirect_to => { :action => :index }
before_filter :require_admin_or_api_request, :only => :index
accept_api_auth :index
def index def index
respond_to do |format| @tracker_pages, @trackers = paginate :trackers, :per_page => 10, :order => 'position'
format.html { render :action => "index", :layout => false if request.xhr?
@tracker_pages, @trackers = paginate :trackers, :per_page => 10, :order => 'position'
render :action => "index", :layout => false if request.xhr?
}
format.api {
@trackers = Tracker.all
}
end
end end
def new def new
@tracker ||= Tracker.new(params[:tracker])
@trackers = Tracker.find :all, :order => 'position'
@projects = Project.find(:all)
end
def create
@tracker = Tracker.new(params[:tracker]) @tracker = Tracker.new(params[:tracker])
if request.post? and @tracker.save if request.post? and @tracker.save
# workflow copy # workflow copy
@@ -51,27 +38,20 @@ class TrackersController < ApplicationController
redirect_to :action => 'index' redirect_to :action => 'index'
return return
end end
new @trackers = Tracker.find :all, :order => 'position'
render :action => 'new' @projects = Project.find(:all)
end end
def edit def edit
@tracker ||= Tracker.find(params[:id])
@projects = Project.find(:all)
end
def update
@tracker = Tracker.find(params[:id]) @tracker = Tracker.find(params[:id])
if request.put? and @tracker.update_attributes(params[:tracker]) if request.post? and @tracker.update_attributes(params[:tracker])
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'index' redirect_to :action => 'index'
return return
end end
edit @projects = Project.find(:all)
render :action => 'edit'
end end
verify :method => :delete, :only => :destroy, :redirect_to => { :action => :index }
def destroy def destroy
@tracker = Tracker.find(params[:id]) @tracker = Tracker.find(params[:id])
unless @tracker.issues.empty? unless @tracker.issues.empty?
@@ -80,5 +60,5 @@ class TrackersController < ApplicationController
@tracker.destroy @tracker.destroy
end end
redirect_to :action => 'index' redirect_to :action => 'index'
end end
end end
+21 -21
View File
@@ -5,19 +5,19 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class UsersController < ApplicationController class UsersController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin, :except => :show before_filter :require_admin, :except => :show
before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership] before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership]
accept_api_auth :index, :show, :create, :update, :destroy accept_api_auth :index, :show, :create, :update, :destroy
@@ -25,22 +25,22 @@ class UsersController < ApplicationController
helper :sort helper :sort
include SortHelper include SortHelper
helper :custom_fields helper :custom_fields
include CustomFieldsHelper include CustomFieldsHelper
def index def index
sort_init 'login', 'asc' sort_init 'login', 'asc'
sort_update %w(login firstname lastname mail admin created_on last_login_on) sort_update %w(login firstname lastname mail admin created_on last_login_on)
case params[:format] case params[:format]
when 'xml', 'json' when 'xml', 'json'
@offset, @limit = api_offset_and_limit @offset, @limit = api_offset_and_limit
else else
@limit = per_page_option @limit = per_page_option
end end
scope = User scope = User
scope = scope.in_group(params[:group_id].to_i) if params[:group_id].present? scope = scope.in_group(params[:group_id].to_i) if params[:group_id].present?
@status = params[:status] ? params[:status].to_i : 1 @status = params[:status] ? params[:status].to_i : 1
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status]) c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
@@ -48,7 +48,7 @@ class UsersController < ApplicationController
name = "%#{params[:name].strip.downcase}%" name = "%#{params[:name].strip.downcase}%"
c << ["LOWER(login) LIKE ? OR LOWER(firstname) LIKE ? OR LOWER(lastname) LIKE ? OR LOWER(mail) LIKE ?", name, name, name, name] c << ["LOWER(login) LIKE ? OR LOWER(firstname) LIKE ? OR LOWER(lastname) LIKE ? OR LOWER(mail) LIKE ?", name, name, name, name]
end end
@user_count = scope.count(:conditions => c.conditions) @user_count = scope.count(:conditions => c.conditions)
@user_pages = Paginator.new self, @user_count, @limit, params['page'] @user_pages = Paginator.new self, @user_count, @limit, params['page']
@offset ||= @user_pages.current.offset @offset ||= @user_pages.current.offset
@@ -66,21 +66,21 @@ class UsersController < ApplicationController
format.api format.api
end end
end end
def show def show
# show projects based on current user visibility # show projects based on current user visibility
@memberships = @user.memberships.all(:conditions => Project.visible_condition(User.current)) @memberships = @user.memberships.all(:conditions => Project.visible_condition(User.current))
events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10) events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
@events_by_day = events.group_by(&:event_date) @events_by_day = events.group_by(&:event_date)
unless User.current.admin? unless User.current.admin?
if !@user.active? || (@user != User.current && @memberships.empty? && events.empty?) if !@user.active? || (@user != User.current && @memberships.empty? && events.empty?)
render_404 render_404
return return
end end
end end
respond_to do |format| respond_to do |format|
format.html { render :layout => 'base' } format.html { render :layout => 'base' }
format.api format.api
@@ -91,7 +91,7 @@ class UsersController < ApplicationController
@user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option) @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
@auth_sources = AuthSource.find(:all) @auth_sources = AuthSource.find(:all)
end end
verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
def create def create
@user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option) @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
@@ -109,12 +109,12 @@ class UsersController < ApplicationController
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : []) @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
Mailer.deliver_account_information(@user, params[:user][:password]) if params[:send_information] Mailer.deliver_account_information(@user, params[:user][:password]) if params[:send_information]
respond_to do |format| respond_to do |format|
format.html { format.html {
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to(params[:continue] ? redirect_to(params[:continue] ?
{:controller => 'users', :action => 'new'} : {:controller => 'users', :action => 'new'} :
{:controller => 'users', :action => 'edit', :id => @user} {:controller => 'users', :action => 'edit', :id => @user}
) )
} }
@@ -136,7 +136,7 @@ class UsersController < ApplicationController
@auth_sources = AuthSource.find(:all) @auth_sources = AuthSource.find(:all)
@membership ||= Member.new @membership ||= Member.new
end end
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
def update def update
@user.admin = params[:user][:admin] if params[:user][:admin] @user.admin = params[:user][:admin] if params[:user][:admin]
@@ -160,7 +160,7 @@ class UsersController < ApplicationController
elsif @user.active? && params[:send_information] && !params[:user][:password].blank? && @user.auth_source_id.nil? elsif @user.active? && params[:send_information] && !params[:user][:password].blank? && @user.auth_source_id.nil?
Mailer.deliver_account_information(@user, params[:user][:password]) Mailer.deliver_account_information(@user, params[:user][:password])
end end
respond_to do |format| respond_to do |format|
format.html { format.html {
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
@@ -213,7 +213,7 @@ class UsersController < ApplicationController
end end
end end
end end
def destroy_membership def destroy_membership
@membership = Member.find(params[:membership_id]) @membership = Member.find(params[:membership_id])
if request.post? && @membership.deletable? if request.post? && @membership.deletable?
@@ -224,9 +224,9 @@ class UsersController < ApplicationController
format.js { render(:update) {|page| page.replace_html "tab-content-memberships", :partial => 'users/memberships'} } format.js { render(:update) {|page| page.replace_html "tab-content-memberships", :partial => 'users/memberships'} }
end end
end end
private private
def find_user def find_user
if params[:id] == 'current' if params[:id] == 'current'
require_login || return require_login || return
+41 -75
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -23,59 +23,45 @@ class VersionsController < ApplicationController
before_filter :find_project, :only => [:index, :new, :create, :close_completed] before_filter :find_project, :only => [:index, :new, :create, :close_completed]
before_filter :authorize before_filter :authorize
accept_api_auth :index, :show, :create, :update, :destroy
helper :custom_fields helper :custom_fields
helper :projects helper :projects
def index def index
respond_to do |format| @trackers = @project.trackers.find(:all, :order => 'position')
format.html { retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?})
@trackers = @project.trackers.find(:all, :order => 'position') @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?}) project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id]
@with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id] @versions = @project.shared_versions || []
@versions += @project.rolled_up_versions.visible if @with_subprojects
@versions = @project.shared_versions || [] @versions = @versions.uniq.sort
@versions += @project.rolled_up_versions.visible if @with_subprojects @versions.reject! {|version| version.closed? || version.completed? } unless params[:completed]
@versions = @versions.uniq.sort
@versions.reject! {|version| version.closed? || version.completed? } unless params[:completed] @issues_by_version = {}
unless @selected_tracker_ids.empty?
@issues_by_version = {} @versions.each do |version|
unless @selected_tracker_ids.empty? issues = version.fixed_issues.visible.find(:all,
@versions.each do |version| :include => [:project, :status, :tracker, :priority],
issues = version.fixed_issues.visible.find(:all, :conditions => {:tracker_id => @selected_tracker_ids, :project_id => project_ids},
:include => [:project, :status, :tracker, :priority], :order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id")
:conditions => {:tracker_id => @selected_tracker_ids, :project_id => project_ids}, @issues_by_version[version] = issues
:order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id") end
@issues_by_version[version] = issues
end
end
@versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
}
format.api {
@versions = @project.shared_versions.all
}
end end
@versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
end end
def show def show
respond_to do |format| @issues = @version.fixed_issues.visible.find(:all,
format.html { :include => [:status, :tracker, :priority],
@issues = @version.fixed_issues.visible.find(:all, :order => "#{Tracker.table_name}.position, #{Issue.table_name}.id")
:include => [:status, :tracker, :priority],
:order => "#{Tracker.table_name}.position, #{Issue.table_name}.id")
}
format.api
end
end end
def new def new
@version = @project.versions.build @version = @project.versions.build
if params[:version] if params[:version]
attributes = params[:version].dup attributes = params[:version].dup
attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing']) attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
@version.safe_attributes = attributes @version.attributes = attributes
end end
end end
@@ -85,7 +71,7 @@ class VersionsController < ApplicationController
if params[:version] if params[:version]
attributes = params[:version].dup attributes = params[:version].dup
attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing']) attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
@version.safe_attributes = attributes @version.attributes = attributes
end end
if request.post? if request.post?
@@ -93,7 +79,7 @@ class VersionsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html do format.html do
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_back_or_default :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
end end
format.js do format.js do
# IE doesn't support the replace_html rjs method for select box options # IE doesn't support the replace_html rjs method for select box options
@@ -101,9 +87,6 @@ class VersionsController < ApplicationController
content_tag('select', '<option></option>' + version_options_for_select(@project.shared_versions.open, @version), :id => 'issue_fixed_version_id', :name => 'issue[fixed_version_id]') content_tag('select', '<option></option>' + version_options_for_select(@project.shared_versions.open, @version), :id => 'issue_fixed_version_id', :name => 'issue[fixed_version_id]')
} }
end end
format.api do
render :action => 'show', :status => :created, :location => version_url(@version)
end
end end
else else
respond_to do |format| respond_to do |format|
@@ -111,7 +94,6 @@ class VersionsController < ApplicationController
format.js do format.js do
render(:update) {|page| page.alert(@version.errors.full_messages.join('\n')) } render(:update) {|page| page.alert(@version.errors.full_messages.join('\n')) }
end end
format.api { render_validation_errors(@version) }
end end
end end
end end
@@ -119,29 +101,22 @@ class VersionsController < ApplicationController
def edit def edit
end end
def update def update
if request.put? && params[:version] if request.put? && params[:version]
attributes = params[:version].dup attributes = params[:version].dup
attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing']) attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing'])
@version.safe_attributes = attributes if @version.update_attributes(attributes)
if @version.save flash[:notice] = l(:notice_successful_update)
respond_to do |format| redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_back_or_default :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
}
format.api { head :ok }
end
else else
respond_to do |format| respond_to do |format|
format.html { render :action => 'edit' } format.html { render :action => 'edit' }
format.api { render_validation_errors(@version) }
end end
end end
end end
end end
def close_completed def close_completed
if request.put? if request.put?
@project.close_completed_versions @project.close_completed_versions
@@ -149,25 +124,16 @@ class VersionsController < ApplicationController
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
end end
verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
def destroy def destroy
if @version.fixed_issues.empty? if @version.fixed_issues.empty?
@version.destroy @version.destroy
respond_to do |format| redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
format.html { redirect_back_or_default :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project }
format.api { head :ok }
end
else else
respond_to do |format| flash[:error] = l(:notice_unable_delete_version)
format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
flash[:error] = l(:notice_unable_delete_version)
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
}
format.api { head :unprocessable_entity }
end
end end
end end
def status_by def status_by
respond_to do |format| respond_to do |format|
format.html { render :action => 'show' } format.html { render :action => 'show' }
+9 -9
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -19,11 +19,11 @@ class WatchersController < ApplicationController
before_filter :find_project before_filter :find_project
before_filter :require_login, :check_project_privacy, :only => [:watch, :unwatch] before_filter :require_login, :check_project_privacy, :only => [:watch, :unwatch]
before_filter :authorize, :only => [:new, :destroy] before_filter :authorize, :only => [:new, :destroy]
verify :method => :post, verify :method => :post,
:only => [ :watch, :unwatch ], :only => [ :watch, :unwatch ],
:render => { :nothing => true, :status => :method_not_allowed } :render => { :nothing => true, :status => :method_not_allowed }
def watch def watch
if @watched.respond_to?(:visible?) && !@watched.visible?(User.current) if @watched.respond_to?(:visible?) && !@watched.visible?(User.current)
render_403 render_403
@@ -31,11 +31,11 @@ class WatchersController < ApplicationController
set_watcher(User.current, true) set_watcher(User.current, true)
end end
end end
def unwatch def unwatch
set_watcher(User.current, false) set_watcher(User.current, false)
end end
def new def new
@watcher = Watcher.new(params[:watcher]) @watcher = Watcher.new(params[:watcher])
@watcher.watchable = @watched @watcher.watchable = @watched
@@ -51,7 +51,7 @@ class WatchersController < ApplicationController
rescue ::ActionController::RedirectBackError rescue ::ActionController::RedirectBackError
render :text => 'Watcher added.', :layout => true render :text => 'Watcher added.', :layout => true
end end
def destroy def destroy
@watched.set_watcher(User.find(params[:user_id]), false) if request.post? @watched.set_watcher(User.find(params[:user_id]), false) if request.post?
respond_to do |format| respond_to do |format|
@@ -63,7 +63,7 @@ class WatchersController < ApplicationController
end end
end end
end end
private private
def find_project def find_project
klass = Object.const_get(params[:object_type].camelcase) klass = Object.const_get(params[:object_type].camelcase)
@@ -73,7 +73,7 @@ private
rescue rescue
render_404 render_404
end end
def set_watcher(user, watching) def set_watcher(user, watching)
@watched.set_watcher(user, watching) @watched.set_watcher(user, watching)
respond_to do |format| respond_to do |format|
+5 -5
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -22,7 +22,7 @@ class WelcomeController < ApplicationController
@news = News.latest User.current @news = News.latest User.current
@projects = Project.latest User.current @projects = Project.latest User.current
end end
def robots def robots
@projects = Project.all_public.active @projects = Project.all_public.active
render :layout => false, :content_type => 'text/plain' render :layout => false, :content_type => 'text/plain'
+3 -28
View File
@@ -40,7 +40,6 @@ class WikiController < ApplicationController
helper :attachments helper :attachments
include AttachmentsHelper include AttachmentsHelper
helper :watchers helper :watchers
include Redmine::Export::PDF
# List of pages, sorted alphabetically and by parent (hierarchy) # List of pages, sorted alphabetically and by parent (hierarchy)
def index def index
@@ -72,10 +71,7 @@ class WikiController < ApplicationController
end end
@content = @page.content_for_version(params[:version]) @content = @page.content_for_version(params[:version])
if User.current.allowed_to?(:export_wiki_pages, @project) if User.current.allowed_to?(:export_wiki_pages, @project)
if params[:format] == 'pdf' if params[:format] == 'html'
send_data(wiki_to_pdf(@page, @project), :type => 'application/pdf', :filename => "#{@page.title}.pdf")
return
elsif params[:format] == 'html'
export = render_to_string :action => 'export', :layout => false export = render_to_string :action => 'export', :layout => false
send_data(export, :type => 'text/html', :filename => "#{@page.title}.html") send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
return return
@@ -85,10 +81,6 @@ class WikiController < ApplicationController
end end
end end
@editable = editable? @editable = editable?
@sections_editable = @editable && User.current.allowed_to?(:edit_wiki_pages, @page.project) &&
@content.current_version? &&
Redmine::WikiFormatting.supports_section_edit?
render :action => 'show' render :action => 'show'
end end
@@ -104,13 +96,6 @@ class WikiController < ApplicationController
# To prevent StaleObjectError exception when reverting to a previous version # To prevent StaleObjectError exception when reverting to a previous version
@content.version = @page.content.version @content.version = @page.content.version
@text = @content.text
if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
@section = params[:section].to_i
@text, @section_hash = Redmine::WikiFormatting.formatter.new(@text).get_section(@section)
render_404 if @text.blank?
end
end end
verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
@@ -131,17 +116,7 @@ class WikiController < ApplicationController
redirect_to :action => 'show', :project_id => @project, :id => @page.title redirect_to :action => 'show', :project_id => @project, :id => @page.title
return return
end end
@content.attributes = params[:content]
@content.comments = params[:content][:comments]
@text = params[:content][:text]
if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
@section = params[:section].to_i
@section_hash = params[:section_hash]
@content.text = Redmine::WikiFormatting.formatter.new(@content.text).update_section(params[:section].to_i, @text, @section_hash)
else
@content.version = params[:content][:version]
@content.text = @text
end
@content.author = User.current @content.author = User.current
# if page is new @page.save will also save content, but not if page isn't a new record # 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) if (@page.new_record? ? @page.save : @content.save)
@@ -153,7 +128,7 @@ class WikiController < ApplicationController
render :action => 'edit' render :action => 'edit'
end end
rescue ActiveRecord::StaleObjectError, Redmine::WikiFormatting::StaleSectionError rescue ActiveRecord::StaleObjectError
# Optimistic locking exception # Optimistic locking exception
flash.now[:error] = l(:notice_locking_conflict) flash.now[:error] = l(:notice_locking_conflict)
render :action => 'edit' render :action => 'edit'
+7 -7
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -18,11 +18,11 @@
class WikisController < ApplicationController class WikisController < ApplicationController
menu_item :settings menu_item :settings
before_filter :find_project, :authorize before_filter :find_project, :authorize
# Create or update a project's wiki # Create or update a project's wiki
def edit def edit
@wiki = @project.wiki || Wiki.new(:project => @project) @wiki = @project.wiki || Wiki.new(:project => @project)
@wiki.safe_attributes = params[:wiki] @wiki.attributes = params[:wiki]
@wiki.save if request.post? @wiki.save if request.post?
render(:update) {|page| page.replace_html "tab-content-wiki", :partial => 'projects/settings/wiki'} render(:update) {|page| page.replace_html "tab-content-wiki", :partial => 'projects/settings/wiki'}
end end
@@ -32,6 +32,6 @@ class WikisController < ApplicationController
if request.post? && params[:confirm] && @project.wiki if request.post? && params[:confirm] && @project.wiki
@project.wiki.destroy @project.wiki.destroy
redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'wiki' redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'wiki'
end end
end end
end end
+16 -16
View File
@@ -1,42 +1,42 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2008 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class WorkflowsController < ApplicationController class WorkflowsController < ApplicationController
layout 'admin' layout 'admin'
before_filter :require_admin before_filter :require_admin
before_filter :find_roles before_filter :find_roles
before_filter :find_trackers before_filter :find_trackers
def index def index
@workflow_counts = Workflow.count_by_tracker_and_role @workflow_counts = Workflow.count_by_tracker_and_role
end end
def edit def edit
@role = Role.find_by_id(params[:role_id]) @role = Role.find_by_id(params[:role_id])
@tracker = Tracker.find_by_id(params[:tracker_id]) @tracker = Tracker.find_by_id(params[:tracker_id])
if request.post? if request.post?
Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id]) Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
(params[:issue_status] || []).each { |status_id, transitions| (params[:issue_status] || []).each { |status_id, transitions|
transitions.each { |new_status_id, options| transitions.each { |new_status_id, options|
author = options.is_a?(Array) && options.include?('author') && !options.include?('always') author = options.is_a?(Array) && options.include?('author') && !options.include?('always')
assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always') assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always')
@role.workflows.build(:tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee) @role.workflows.build(:tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee)
} }
} }
if @role.save if @role.save
@@ -45,13 +45,13 @@ class WorkflowsController < ApplicationController
return return
end end
end end
@used_statuses_only = (params[:used_statuses_only] == '0' ? false : true) @used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
if @tracker && @used_statuses_only && @tracker.issue_statuses.any? if @tracker && @used_statuses_only && @tracker.issue_statuses.any?
@statuses = @tracker.issue_statuses @statuses = @tracker.issue_statuses
end end
@statuses ||= IssueStatus.find(:all, :order => 'position') @statuses ||= IssueStatus.find(:all, :order => 'position')
if @tracker && @role && @statuses.any? if @tracker && @role && @statuses.any?
workflows = Workflow.all(:conditions => {:role_id => @role.id, :tracker_id => @tracker.id}) workflows = Workflow.all(:conditions => {:role_id => @role.id, :tracker_id => @tracker.id})
@workflows = {} @workflows = {}
@@ -60,9 +60,9 @@ class WorkflowsController < ApplicationController
@workflows['assignee'] = workflows.select {|w| w.assignee} @workflows['assignee'] = workflows.select {|w| w.assignee}
end end
end end
def copy def copy
if params[:source_tracker_id].blank? || params[:source_tracker_id] == 'any' if params[:source_tracker_id].blank? || params[:source_tracker_id] == 'any'
@source_tracker = nil @source_tracker = nil
else else
@@ -73,10 +73,10 @@ class WorkflowsController < ApplicationController
else else
@source_role = Role.find_by_id(params[:source_role_id].to_i) @source_role = Role.find_by_id(params[:source_role_id].to_i)
end end
@target_trackers = params[:target_tracker_ids].blank? ? nil : Tracker.find_all_by_id(params[:target_tracker_ids]) @target_trackers = params[:target_tracker_ids].blank? ? nil : Tracker.find_all_by_id(params[:target_tracker_ids])
@target_roles = params[:target_role_ids].blank? ? nil : Role.find_all_by_id(params[:target_role_ids]) @target_roles = params[:target_role_ids].blank? ? nil : Role.find_all_by_id(params[:target_role_ids])
if request.post? if request.post?
if params[:source_tracker_id].blank? || params[:source_role_id].blank? || (@source_tracker.nil? && @source_role.nil?) if params[:source_tracker_id].blank? || params[:source_role_id].blank? || (@source_tracker.nil? && @source_role.nil?)
flash.now[:error] = l(:error_workflow_copy_source) flash.now[:error] = l(:error_workflow_copy_source)
@@ -95,7 +95,7 @@ class WorkflowsController < ApplicationController
def find_roles def find_roles
@roles = Role.find(:all, :order => 'builtin, position') @roles = Role.find(:all, :order => 'builtin, position')
end end
def find_trackers def find_trackers
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
end end
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+5 -7
View File
@@ -1,25 +1,23 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module AdminHelper module AdminHelper
def project_status_options_for_select(selected) def project_status_options_for_select(selected)
options_for_select([[l(:label_all), ''], options_for_select([[l(:label_all), ''],
[l(:status_active), 1]], selected) [l(:status_active), 1]], selected)
end end
end end
+60 -180
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -82,7 +80,7 @@ module ApplicationHelper
subject = truncate(subject, :length => options[:truncate]) subject = truncate(subject, :length => options[:truncate])
end end
end end
s = link_to "#{h(issue.tracker)} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue}, s = link_to "#{issue.tracker} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue},
:class => issue.css_classes, :class => issue.css_classes,
:title => title :title => title
s << ": #{h subject}" if subject s << ": #{h subject}" if subject
@@ -97,10 +95,8 @@ module ApplicationHelper
def link_to_attachment(attachment, options={}) def link_to_attachment(attachment, options={})
text = options.delete(:text) || attachment.filename text = options.delete(:text) || attachment.filename
action = options.delete(:download) ? 'download' : 'show' action = options.delete(:download) ? 'download' : 'show'
link_to(h(text),
{:controller => 'attachments', :action => action, link_to(h(text), {:controller => 'attachments', :action => action, :id => attachment, :filename => attachment.filename }, options)
:id => attachment, :filename => attachment.filename },
options)
end end
# Generates a link to a SCM revision # Generates a link to a SCM revision
@@ -110,7 +106,7 @@ module ApplicationHelper
text = options.delete(:text) || format_revision(revision) text = options.delete(:text) || format_revision(revision)
rev = revision.respond_to?(:identifier) ? revision.identifier : revision rev = revision.respond_to?(:identifier) ? revision.identifier : revision
link_to(h(text), {:controller => 'repositories', :action => 'revision', :id => project, :rev => rev}, link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => rev},
:title => l(:label_revision_id, format_revision(revision))) :title => l(:label_revision_id, format_revision(revision)))
end end
@@ -204,7 +200,7 @@ module ApplicationHelper
end end
content << "</ul>\n" content << "</ul>\n"
end end
content.html_safe content
end end
# Renders flash messages # Renders flash messages
@@ -213,7 +209,7 @@ module ApplicationHelper
flash.each do |k,v| flash.each do |k,v|
s << content_tag('div', v, :class => "flash #{k}") s << content_tag('div', v, :class => "flash #{k}")
end end
s.html_safe s
end end
# Renders tabs and their content # Renders tabs and their content
@@ -237,7 +233,7 @@ module ApplicationHelper
{ :value => url_for(:controller => 'projects', :action => 'show', :id => p, :jump => current_menu_item) } { :value => url_for(:controller => 'projects', :action => 'show', :id => p, :jump => current_menu_item) }
end end
s << '</select>' s << '</select>'
s.html_safe s
end end
end end
@@ -254,7 +250,7 @@ module ApplicationHelper
tag_options.merge!(yield(project)) if block_given? tag_options.merge!(yield(project)) if block_given?
s << content_tag('option', name_prefix + h(project), tag_options) s << content_tag('option', name_prefix + h(project), tag_options)
end end
s.html_safe s
end end
# Yields the given block for each project with its level in the tree # Yields the given block for each project with its level in the tree
@@ -285,7 +281,7 @@ module ApplicationHelper
end end
s << ("</li></ul>\n" * ancestors.size) s << ("</li></ul>\n" * ancestors.size)
end end
s.html_safe s
end end
def principals_check_box_tags(name, principals) def principals_check_box_tags(name, principals)
@@ -293,20 +289,6 @@ module ApplicationHelper
principals.sort.each do |principal| principals.sort.each do |principal|
s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n" s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n"
end end
s.html_safe
end
# Returns a string for users/groups option tags
def principals_options_for_select(collection, selected=nil)
s = ''
groups = ''
collection.sort.each do |element|
selected_attribute = ' selected="selected"' if option_value_selected?(element, selected)
(element.is_a?(Group) ? groups : s) << %(<option value="#{element.id}"#{selected_attribute}>#{h element.name}</option>)
end
unless groups.empty?
s << %(<optgroup label="#{h(l(:label_group_plural))}">#{groups}</optgroup>)
end
s s
end end
@@ -326,11 +308,11 @@ module ApplicationHelper
end end
def html_hours(text) def html_hours(text)
text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>').html_safe text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>')
end end
def authoring(created, author, options={}) def authoring(created, author, options={})
l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)).html_safe l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created))
end end
def time_tag(time) def time_tag(time)
@@ -357,10 +339,7 @@ module ApplicationHelper
html = '' html = ''
if paginator.current.previous if paginator.current.previous
# \xc2\xab(utf-8) = &#171; html << link_to_content_update('&#171; ' + l(:label_previous), url_param.merge(page_param => paginator.current.previous)) + ' '
html << link_to_content_update(
"\xc2\xab " + l(:label_previous),
url_param.merge(page_param => paginator.current.previous)) + ' '
end end
html << (pagination_links_each(paginator, options) do |n| html << (pagination_links_each(paginator, options) do |n|
@@ -368,10 +347,7 @@ module ApplicationHelper
end || '') end || '')
if paginator.current.next if paginator.current.next
# \xc2\xbb(utf-8) = &#187; html << ' ' + link_to_content_update((l(:label_next) + ' &#187;'), url_param.merge(page_param => paginator.current.next))
html << ' ' + link_to_content_update(
(l(:label_next) + " \xc2\xbb"),
url_param.merge(page_param => paginator.current.next))
end end
unless count.nil? unless count.nil?
@@ -381,7 +357,7 @@ module ApplicationHelper
end end
end end
html.html_safe html
end end
def per_page_links(selected=nil) def per_page_links(selected=nil)
@@ -391,30 +367,22 @@ module ApplicationHelper
links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil
end end
def reorder_links(name, url, method = :post) def reorder_links(name, url)
link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), url.merge({"#{name}[move_to]" => 'highest'}), :method => :post, :title => l(:label_sort_highest)) +
url.merge({"#{name}[move_to]" => 'highest'}), link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), url.merge({"#{name}[move_to]" => 'higher'}), :method => :post, :title => l(:label_sort_higher)) +
:method => method, :title => l(:label_sort_highest)) + link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), url.merge({"#{name}[move_to]" => 'lower'}), :method => :post, :title => l(:label_sort_lower)) +
link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), url.merge({"#{name}[move_to]" => 'lowest'}), :method => :post, :title => l(:label_sort_lowest))
url.merge({"#{name}[move_to]" => 'higher'}),
:method => method, :title => l(:label_sort_higher)) +
link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)),
url.merge({"#{name}[move_to]" => 'lower'}),
:method => method, :title => l(:label_sort_lower)) +
link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)),
url.merge({"#{name}[move_to]" => 'lowest'}),
:method => method, :title => l(:label_sort_lowest))
end end
def breadcrumb(*args) def breadcrumb(*args)
elements = args.flatten elements = args.flatten
elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'breadcrumb') : nil elements.any? ? content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb') : nil
end end
def other_formats_links(&block) def other_formats_links(&block)
concat('<p class="other-formats">'.html_safe + l(:label_export_to)) concat('<p class="other-formats">' + l(:label_export_to))
yield Redmine::Views::OtherFormatsBuilder.new(self) yield Redmine::Views::OtherFormatsBuilder.new(self)
concat('</p>'.html_safe) concat('</p>')
end end
def page_header_title def page_header_title
@@ -427,21 +395,22 @@ module ApplicationHelper
root = ancestors.shift root = ancestors.shift
b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') b << link_to_project(root, {:jump => current_menu_item}, :class => 'root')
if ancestors.size > 2 if ancestors.size > 2
b << "\xe2\x80\xa6" b << '&#8230;'
ancestors = ancestors[-2, 2] ancestors = ancestors[-2, 2]
end end
b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') } b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') }
end end
b << h(@project) b << h(@project)
b.join(" \xc2\xbb ").html_safe b.join(' &#187; ')
end end
end end
def html_title(*args) def html_title(*args)
if args.empty? if args.empty?
title = @html_title || [] title = []
title << @project.name if @project title << @project.name if @project
title << Setting.app_title unless Setting.app_title == title.last title += @html_title if @html_title
title << Setting.app_title
title.select {|t| !t.blank? }.join(' - ') title.select {|t| !t.blank? }.join(' - ')
else else
@html_title ||= [] @html_title ||= []
@@ -487,19 +456,14 @@ module ApplicationHelper
project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
only_path = options.delete(:only_path) == false ? false : true only_path = options.delete(:only_path) == false ? false : true
text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) }
@parsed_headings = [] @parsed_headings = []
@heading_anchors = {}
@current_section = 0 if options[:edit_section_links]
parse_sections(text, project, obj, attr, only_path, options)
text = parse_non_pre_blocks(text) do |text| text = parse_non_pre_blocks(text) do |text|
[:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_macros].each do |method_name| [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links, :parse_headings].each do |method_name|
send method_name, text, project, obj, attr, only_path, options send method_name, text, project, obj, attr, only_path, options
end end
end end
parse_headings(text, project, obj, attr, only_path, options)
if @parsed_headings.any? if @parsed_headings.any?
replace_toc(text, @parsed_headings) replace_toc(text, @parsed_headings)
@@ -534,26 +498,26 @@ module ApplicationHelper
while tag = tags.pop while tag = tags.pop
parsed << "</#{tag}>" parsed << "</#{tag}>"
end end
parsed.html_safe parsed
end end
def parse_inline_attachments(text, project, obj, attr, only_path, options) def parse_inline_attachments(text, project, obj, attr, only_path, options)
# when using an image link, try to use an attachment, if possible # when using an image link, try to use an attachment, if possible
if options[:attachments] || (obj && obj.respond_to?(:attachments)) if options[:attachments] || (obj && obj.respond_to?(:attachments))
attachments = options[:attachments] || obj.attachments attachments = nil
text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m| text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m|
filename, ext, alt, alttext = $1.downcase, $2, $3, $4 filename, ext, alt, alttext = $1.downcase, $2, $3, $4
attachments ||= (options[:attachments] || obj.attachments).sort_by(&:created_on).reverse
# search for the picture in attachments # search for the picture in attachments
if found = Attachment.latest_attach(attachments, filename) if found = attachments.detect { |att| att.filename.downcase == filename }
image_url = url_for :only_path => only_path, :controller => 'attachments', image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found
:action => 'download', :id => found
desc = found.description.to_s.gsub('"', '') desc = found.description.to_s.gsub('"', '')
if !desc.blank? && alttext.blank? if !desc.blank? && alttext.blank?
alt = " title=\"#{desc}\" alt=\"#{desc}\"" alt = " title=\"#{desc}\" alt=\"#{desc}\""
end end
"src=\"#{image_url}\"#{alt}".html_safe "src=\"#{image_url}\"#{alt}"
else else
m.html_safe m
end end
end end
end end
@@ -594,19 +558,19 @@ module ApplicationHelper
else else
case options[:wiki_links] case options[:wiki_links]
when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '') when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '')
when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export when :anchor; "##{title}" # used for single-file wiki export
else else
wiki_page_id = page.present? ? Wiki.titleize(page) : nil wiki_page_id = page.present? ? Wiki.titleize(page) : nil
url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project, :id => wiki_page_id, :anchor => anchor) url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project, :id => wiki_page_id, :anchor => anchor)
end end
end end
link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new'))) link_to((title || page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new')))
else else
# project or wiki doesn't exist # project or wiki doesn't exist
all.html_safe all
end end
else else
all.html_safe all
end end
end end
end end
@@ -644,7 +608,7 @@ module ApplicationHelper
# identifier:version:1.0.0 # identifier:version:1.0.0
# identifier:source:some/file # identifier:source:some/file
def parse_redmine_links(text, project, obj, attr, only_path, options) def parse_redmine_links(text, project, obj, attr, only_path, options)
text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-]+):)?(attachment|document|version|forum|news|commit|source|export|message|project)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|,|\s|\]|<|$)}) do |m| text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-]+):)?(attachment|document|version|commit|source|export|message|project)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]]\W)|,|\s|\]|<|$)}) do |m|
leading, esc, project_prefix, project_identifier, prefix, sep, identifier = $1, $2, $3, $4, $5, $7 || $9, $8 || $10 leading, esc, project_prefix, project_identifier, prefix, sep, identifier = $1, $2, $3, $4, $5, $7 || $9, $8 || $10
link = nil link = nil
if project_identifier if project_identifier
@@ -654,7 +618,7 @@ module ApplicationHelper
if prefix.nil? && sep == 'r' if prefix.nil? && sep == 'r'
# project.changesets.visible raises an SQL error because of a double join on repositories # project.changesets.visible raises an SQL error because of a double join on repositories
if project && project.repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(project.repository.id, identifier)) if project && project.repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(project.repository.id, identifier))
link = link_to(h("#{project_prefix}r#{identifier}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision}, link = link_to("#{project_prefix}r#{identifier}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision},
:class => 'changeset', :class => 'changeset',
:title => truncate_single_line(changeset.comments, :length => 100)) :title => truncate_single_line(changeset.comments, :length => 100))
end end
@@ -681,16 +645,6 @@ module ApplicationHelper
if message = Message.visible.find_by_id(oid, :include => :parent) if message = Message.visible.find_by_id(oid, :include => :parent)
link = link_to_message(message, {:only_path => only_path}, :class => 'message') link = link_to_message(message, {:only_path => only_path}, :class => 'message')
end end
when 'forum'
if board = Board.visible.find_by_id(oid)
link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
:class => 'board'
end
when 'news'
if news = News.visible.find_by_id(oid)
link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
:class => 'news'
end
when 'project' when 'project'
if p = Project.visible.find_by_id(oid) if p = Project.visible.find_by_id(oid)
link = link_to_project(p, {:only_path => only_path}, :class => 'project') link = link_to_project(p, {:only_path => only_path}, :class => 'project')
@@ -710,21 +664,11 @@ module ApplicationHelper
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
:class => 'version' :class => 'version'
end end
when 'forum'
if project && board = project.boards.visible.find_by_name(name)
link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
:class => 'board'
end
when 'news'
if project && news = project.news.visible.find_by_title(name)
link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
:class => 'news'
end
when 'commit' when 'commit'
if project && project.repository && (changeset = Changeset.visible.find(:first, :conditions => ["repository_id = ? AND scmid LIKE ?", project.repository.id, "#{name}%"])) if project && project.repository && (changeset = Changeset.visible.find(:first, :conditions => ["repository_id = ? AND scmid LIKE ?", project.repository.id, "#{name}%"]))
link = link_to h("#{project_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.identifier}, link = link_to h("#{project_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.identifier},
:class => 'changeset', :class => 'changeset',
:title => truncate_single_line(h(changeset.comments), :length => 100) :title => truncate_single_line(changeset.comments, :length => 100)
end end
when 'source', 'export' when 'source', 'export'
if project && project.repository && User.current.allowed_to?(:browse_repository, project) if project && project.repository && User.current.allowed_to?(:browse_repository, project)
@@ -750,26 +694,11 @@ module ApplicationHelper
end end
end end
end end
(leading + (link || "#{project_prefix}#{prefix}#{sep}#{identifier}")).html_safe leading + (link || "#{project_prefix}#{prefix}#{sep}#{identifier}")
end end
end end
HEADING_RE = /(<h(1|2|3|4)( [^>]+)?>(.+?)<\/h(1|2|3|4)>)/i unless const_defined?(:HEADING_RE) HEADING_RE = /<h(1|2|3|4)( [^>]+)?>(.+?)<\/h(1|2|3|4)>/i unless const_defined?(:HEADING_RE)
def parse_sections(text, project, obj, attr, only_path, options)
return unless options[:edit_section_links]
text.gsub!(HEADING_RE) do
@current_section += 1
if @current_section > 1
content_tag('div',
link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)),
:class => 'contextual',
:title => l(:button_edit_section)) + $1
else
$1
end
end
end
# Headings and TOC # Headings and TOC
# Adds ids and links to headings unless options[:headings] is set to false # Adds ids and links to headings unless options[:headings] is set to false
@@ -777,48 +706,14 @@ module ApplicationHelper
return if options[:headings] == false return if options[:headings] == false
text.gsub!(HEADING_RE) do text.gsub!(HEADING_RE) do
level, attrs, content = $2.to_i, $3, $4 level, attrs, content = $1.to_i, $2, $3
item = strip_tags(content).strip item = strip_tags(content).strip
anchor = sanitize_anchor_name(item) anchor = sanitize_anchor_name(item)
# used for single-file wiki export
anchor = "#{obj.page.title}_#{anchor}" if options[:wiki_links] == :anchor && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version))
@heading_anchors[anchor] ||= 0
idx = (@heading_anchors[anchor] += 1)
if idx > 1
anchor = "#{anchor}-#{idx}"
end
@parsed_headings << [level, anchor, item] @parsed_headings << [level, anchor, item]
"<a name=\"#{anchor}\"></a>\n<h#{level} #{attrs}>#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a></h#{level}>" "<a name=\"#{anchor}\"></a>\n<h#{level} #{attrs}>#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a></h#{level}>"
end end
end end
MACROS_RE = /
(!)? # escaping
(
\{\{ # opening tag
([\w]+) # macro name
(\(([^\}]*)\))? # optional arguments
\}\} # closing tag
)
/x unless const_defined?(:MACROS_RE)
# Macros substitution
def parse_macros(text, project, obj, attr, only_path, options)
text.gsub!(MACROS_RE) do
esc, all, macro = $1, $2, $3.downcase
args = ($5 || '').split(',').each(&:strip)
if esc.nil?
begin
exec_macro(macro, obj, args)
rescue => e
"<div class=\"flash error\">Error executing the <strong>#{macro}</strong> macro (#{e})</div>"
end || all
else
all
end
end
end
TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) TOC_RE = /<p>\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE)
# Renders the TOC with given headings # Renders the TOC with given headings
@@ -857,8 +752,7 @@ module ApplicationHelper
text.to_s. text.to_s.
gsub(/\r\n?/, "\n"). # \r\n and \r -> \n gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
gsub(/([^\n]\n)(?=[^\n])/, '\1<br />'). # 1 newline -> br gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
html_safe
end end
def lang_options_for_select(blank=true) def lang_options_for_select(blank=true)
@@ -871,20 +765,10 @@ module ApplicationHelper
content_tag("label", label_text) content_tag("label", label_text)
end end
def labelled_tabular_form_for(*args, &proc) def labelled_tabular_form_for(name, object, options, &proc)
args << {} unless args.last.is_a?(Hash)
options = args.last
options[:html] ||= {} options[:html] ||= {}
options[:html][:class] = 'tabular' unless options[:html].has_key?(:class) options[:html][:class] = 'tabular' unless options[:html].has_key?(:class)
options.merge!({:builder => TabularFormBuilder}) form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
form_for(*args, &proc)
end
def labelled_form_for(*args, &proc)
args << {} unless args.last.is_a?(Hash)
options = args.last
options.merge!({:builder => TabularFormBuilder})
form_for(*args, &proc)
end end
def back_url_hidden_field_tag def back_url_hidden_field_tag
@@ -895,7 +779,7 @@ module ApplicationHelper
def check_all_links(form_name) def check_all_links(form_name)
link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") + link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
" | ".html_safe + " | " +
link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)") link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
end end
@@ -908,11 +792,11 @@ module ApplicationHelper
legend = options[:legend] || '' legend = options[:legend] || ''
content_tag('table', content_tag('table',
content_tag('tr', content_tag('tr',
(pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : ''.html_safe) + (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : '') +
(pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : ''.html_safe) + (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : '') +
(pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : ''.html_safe) (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : '')
), :class => 'progress', :style => "width: #{width};").html_safe + ), :class => 'progress', :style => "width: #{width};") +
content_tag('p', legend, :class => 'pourcent').html_safe content_tag('p', legend, :class => 'pourcent')
end end
def checked_image(checked=true) def checked_image(checked=true)
@@ -950,7 +834,7 @@ module ApplicationHelper
options[:class] << ' disabled' options[:class] << ' disabled'
url = '#' url = '#'
end end
link_to h(name), url, options link_to name, url, options
end end
def calendar_for(field_id) def calendar_for(field_id)
@@ -993,10 +877,6 @@ module ApplicationHelper
(@has_content && @has_content[name]) || false (@has_content && @has_content[name]) || false
end end
def email_delivery_enabled?
!!ActionMailer::Base.perform_deliveries
end
# Returns the avatar image tag for the given +user+ if avatars are enabled # Returns the avatar image tag for the given +user+ if avatars are enabled
# +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <joe@foo.bar>') # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <joe@foo.bar>')
def avatar(user, options = { }) def avatar(user, options = { })
@@ -1022,17 +902,17 @@ module ApplicationHelper
def javascript_heads def javascript_heads
tags = javascript_include_tag(:defaults) tags = javascript_include_tag(:defaults)
unless User.current.pref.warn_on_leaving_unsaved == '0' unless User.current.pref.warn_on_leaving_unsaved == '0'
tags << "\n".html_safe + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });") tags << "\n" + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });")
end end
tags tags
end end
def favicon def favicon
"<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />".html_safe "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />"
end end
def robot_exclusion_tag def robot_exclusion_tag
'<meta name="robots" content="noindex,follow,noarchive" />'.html_safe '<meta name="robots" content="noindex,follow,noarchive" />'
end end
# Returns true if arg is expected in the API response # Returns true if arg is expected in the API response
+13 -12
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -30,16 +28,19 @@ module AttachmentsHelper
end end
end end
def render_api_attachment(attachment, api) def to_utf8(str)
api.attachment do if str.respond_to?(:force_encoding)
api.id attachment.id str.force_encoding('UTF-8')
api.filename attachment.filename return str if str.valid_encoding?
api.filesize attachment.filesize else
api.content_type attachment.content_type return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
api.description attachment.description end
api.content_url url_for(:controller => 'attachments', :action => 'download', :id => attachment, :filename => attachment.filename, :only_path => false)
api.author(:id => attachment.author.id, :name => attachment.author.name) if attachment.author begin
api.created_on attachment.created_on Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3]
rescue Iconv::InvalidEncoding
# "UTF-8//IGNORE" is not supported on some OS
str
end end
end end
end end
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006-2007 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+4 -25
View File
@@ -1,22 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software
# Copyright (C) 2006-2011 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 CalendarsHelper module CalendarsHelper
def link_to_previous_month(year, month, options={}) def link_to_previous_month(year, month, options={})
target_year, target_month = if month == 1 target_year, target_month = if month == 1
@@ -24,15 +5,14 @@ module CalendarsHelper
else else
[year, month - 1] [year, month - 1]
end end
name = if target_month == 12 name = if target_month == 12
"#{month_name(target_month)} #{target_year}" "#{month_name(target_month)} #{target_year}"
else else
"#{month_name(target_month)}" "#{month_name(target_month)}"
end end
# \xc2\xab(utf-8) = &#171; link_to_month(('&#171; ' + name), target_year, target_month, options)
link_to_month(("\xc2\xab " + name), target_year, target_month, options)
end end
def link_to_next_month(year, month, options={}) def link_to_next_month(year, month, options={})
@@ -48,11 +28,10 @@ module CalendarsHelper
"#{month_name(target_month)}" "#{month_name(target_month)}"
end end
# \xc2\xbb(utf-8) = &#187; link_to_month((name + ' &#187;'), target_year, target_month, options)
link_to_month((name + " \xc2\xbb"), target_year, target_month, options)
end end
def link_to_month(link_name, year, month, options={}) def link_to_month(link_name, year, month, options={})
link_to_content_update(h(link_name), params.merge(:year => year, :month => month)) link_to_content_update(link_name, params.merge(:year => year, :month => month))
end end
end end
+13 -15
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -7,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -31,7 +29,7 @@ module CustomFieldsHelper
{:name => 'DocumentCategoryCustomField', :partial => 'custom_fields/index', :label => DocumentCategory::OptionName} {:name => 'DocumentCategoryCustomField', :partial => 'custom_fields/index', :label => DocumentCategory::OptionName}
] ]
end end
# Return custom field html tag corresponding to its format # Return custom field html tag corresponding to its format
def custom_field_tag(name, custom_value) def custom_field_tag(name, custom_value)
custom_field = custom_value.custom_field custom_field = custom_value.custom_field
@@ -41,7 +39,7 @@ module CustomFieldsHelper
field_format = Redmine::CustomFieldFormat.find_by_name(custom_field.field_format) field_format = Redmine::CustomFieldFormat.find_by_name(custom_field.field_format)
case field_format.try(:edit_as) case field_format.try(:edit_as)
when "date" when "date"
text_field_tag(field_name, custom_value.value, :id => field_id, :size => 10) + text_field_tag(field_name, custom_value.value, :id => field_id, :size => 10) +
calendar_for(field_id) calendar_for(field_id)
when "text" when "text"
text_area_tag(field_name, custom_value.value, :id => field_id, :rows => 3, :style => 'width:90%') text_area_tag(field_name, custom_value.value, :id => field_id, :rows => 3, :style => 'width:90%')
@@ -49,34 +47,34 @@ module CustomFieldsHelper
hidden_field_tag(field_name, '0') + check_box_tag(field_name, '1', custom_value.true?, :id => field_id) hidden_field_tag(field_name, '0') + check_box_tag(field_name, '1', custom_value.true?, :id => field_id)
when "list" when "list"
blank_option = custom_field.is_required? ? blank_option = custom_field.is_required? ?
(custom_field.default_value.blank? ? "<option value=\"\">--- #{l(:actionview_instancetag_blank_option)} ---</option>" : '') : (custom_field.default_value.blank? ? "<option value=\"\">--- #{l(:actionview_instancetag_blank_option)} ---</option>" : '') :
'<option></option>' '<option></option>'
select_tag(field_name, blank_option + options_for_select(custom_field.possible_values_options(custom_value.customized), custom_value.value), :id => field_id) select_tag(field_name, blank_option + options_for_select(custom_field.possible_values_options(custom_value.customized), custom_value.value), :id => field_id)
else else
text_field_tag(field_name, custom_value.value, :id => field_id) text_field_tag(field_name, custom_value.value, :id => field_id)
end end
end end
# Return custom field label tag # Return custom field label tag
def custom_field_label_tag(name, custom_value) def custom_field_label_tag(name, custom_value)
content_tag "label", h(custom_value.custom_field.name) + content_tag "label", custom_value.custom_field.name +
(custom_value.custom_field.is_required? ? " <span class=\"required\">*</span>".html_safe : ""), (custom_value.custom_field.is_required? ? " <span class=\"required\">*</span>" : ""),
:for => "#{name}_custom_field_values_#{custom_value.custom_field.id}", :for => "#{name}_custom_field_values_#{custom_value.custom_field.id}",
:class => (custom_value.errors.empty? ? nil : "error" ) :class => (custom_value.errors.empty? ? nil : "error" )
end end
# Return custom field tag with its label tag # Return custom field tag with its label tag
def custom_field_tag_with_label(name, custom_value) def custom_field_tag_with_label(name, custom_value)
custom_field_label_tag(name, custom_value) + custom_field_tag(name, custom_value) custom_field_label_tag(name, custom_value) + custom_field_tag(name, custom_value)
end end
def custom_field_tag_for_bulk_edit(name, custom_field, projects=nil) def custom_field_tag_for_bulk_edit(name, custom_field, projects=nil)
field_name = "#{name}[custom_field_values][#{custom_field.id}]" field_name = "#{name}[custom_field_values][#{custom_field.id}]"
field_id = "#{name}_custom_field_values_#{custom_field.id}" field_id = "#{name}_custom_field_values_#{custom_field.id}"
field_format = Redmine::CustomFieldFormat.find_by_name(custom_field.field_format) field_format = Redmine::CustomFieldFormat.find_by_name(custom_field.field_format)
case field_format.try(:edit_as) case field_format.try(:edit_as)
when "date" when "date"
text_field_tag(field_name, '', :id => field_id, :size => 10) + text_field_tag(field_name, '', :id => field_id, :size => 10) +
calendar_for(field_id) calendar_for(field_id)
when "text" when "text"
text_area_tag(field_name, '', :id => field_id, :rows => 3, :style => 'width:90%') text_area_tag(field_name, '', :id => field_id, :rows => 3, :style => 'width:90%')
@@ -96,7 +94,7 @@ module CustomFieldsHelper
return "" unless custom_value return "" unless custom_value
format_value(custom_value.value, custom_value.custom_field.field_format) format_value(custom_value.value, custom_value.custom_field.field_format)
end end
# Return a string used to display a custom value # Return a string used to display a custom value
def format_value(value, field_format) def format_value(value, field_format)
Redmine::CustomFieldFormat.format_value(value, field_format) # Proxy Redmine::CustomFieldFormat.format_value(value, field_format) # Proxy
@@ -106,7 +104,7 @@ module CustomFieldsHelper
def custom_field_formats_for_select(custom_field) def custom_field_formats_for_select(custom_field)
Redmine::CustomFieldFormat.as_select(custom_field.class.customized_class.name) Redmine::CustomFieldFormat.as_select(custom_field.class.customized_class.name)
end end
# Renders the custom_values in api views # Renders the custom_values in api views
def render_api_custom_values(custom_values, api) def render_api_custom_values(custom_values, api)
api.array :custom_fields do api.array :custom_fields do
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+5 -7
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -7,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -27,16 +25,16 @@ module GanttHelper
params.merge(gantt.params.merge(:zoom => (gantt.zoom+1))), params.merge(gantt.params.merge(:zoom => (gantt.zoom+1))),
:class => 'icon icon-zoom-in' :class => 'icon icon-zoom-in'
else else
content_tag('span', l(:text_zoom_in), :class => 'icon icon-zoom-in').html_safe content_tag('span', l(:text_zoom_in), :class => 'icon icon-zoom-in')
end end
when :out when :out
if gantt.zoom > 1 if gantt.zoom > 1
link_to_content_update l(:text_zoom_out), link_to_content_update l(:text_zoom_out),
params.merge(gantt.params.merge(:zoom => (gantt.zoom-1))), params.merge(gantt.params.merge(:zoom => (gantt.zoom-1))),
:class => 'icon icon-zoom-out' :class => 'icon icon-zoom-out'
else else
content_tag('span', l(:text_zoom_out), :class => 'icon icon-zoom-out').html_safe content_tag('span', l(:text_zoom_out), :class => 'icon icon-zoom-out')
end end
end end
end end
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2009 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -26,7 +24,7 @@ module GroupsHelper
end end
options options
end end
def group_settings_tabs def group_settings_tabs
tabs = [{:name => 'general', :partial => 'groups/general', :label => :label_general}, tabs = [{:name => 'general', :partial => 'groups/general', :label => :label_general},
{:name => 'users', :partial => 'groups/users', :label => :label_user_plural}, {:name => 'users', :partial => 'groups/users', :label => :label_user_plural},
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-2
View File
@@ -1,4 +1,2 @@
# encoding: utf-8
#
module IssueMovesHelper module IssueMovesHelper
end end
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006-2007 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+57 -38
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -48,13 +46,13 @@ module IssuesHelper
@cached_label_priority ||= l(:field_priority) @cached_label_priority ||= l(:field_priority)
@cached_label_project ||= l(:field_project) @cached_label_project ||= l(:field_project)
(link_to_issue(issue) + "<br /><br />" + link_to_issue(issue) + "<br /><br />" +
"<strong>#{@cached_label_project}</strong>: #{link_to_project(issue.project)}<br />" + "<strong>#{@cached_label_project}</strong>: #{link_to_project(issue.project)}<br />" +
"<strong>#{@cached_label_status}</strong>: #{h(issue.status.name)}<br />" + "<strong>#{@cached_label_status}</strong>: #{issue.status.name}<br />" +
"<strong>#{@cached_label_start_date}</strong>: #{format_date(issue.start_date)}<br />" + "<strong>#{@cached_label_start_date}</strong>: #{format_date(issue.start_date)}<br />" +
"<strong>#{@cached_label_due_date}</strong>: #{format_date(issue.due_date)}<br />" + "<strong>#{@cached_label_due_date}</strong>: #{format_date(issue.due_date)}<br />" +
"<strong>#{@cached_label_assigned_to}</strong>: #{h(issue.assigned_to)}<br />" + "<strong>#{@cached_label_assigned_to}</strong>: #{issue.assigned_to}<br />" +
"<strong>#{@cached_label_priority}</strong>: #{h(issue.priority.name)}").html_safe "<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}"
end end
def issue_heading(issue) def issue_heading(issue)
@@ -74,7 +72,7 @@ module IssuesHelper
end end
s << content_tag('h3', subject) s << content_tag('h3', subject)
s << '</div>' * (ancestors.size + 1) s << '</div>' * (ancestors.size + 1)
s.html_safe s
end end
def render_descendants_tree(issue) def render_descendants_tree(issue)
@@ -89,7 +87,7 @@ module IssuesHelper
:class => "issue issue-#{child.id} hascontextmenu #{level > 0 ? "idnt idnt-#{level}" : nil}") :class => "issue issue-#{child.id} hascontextmenu #{level > 0 ? "idnt idnt-#{level}" : nil}")
end end
s << '</form></table>' s << '</form></table>'
s.html_safe s
end end
def render_custom_fields_rows(issue) def render_custom_fields_rows(issue)
@@ -108,7 +106,7 @@ module IssuesHelper
n += 1 n += 1
end end
s << "</tr>\n" s << "</tr>\n"
s.html_safe s
end end
def issues_destroy_confirmation_message(issues) def issues_destroy_confirmation_message(issues)
@@ -147,7 +145,7 @@ module IssuesHelper
# links to #index on issues/show # links to #index on issues/show
url_params = controller_name == 'issues' ? {:controller => 'issues', :action => 'index', :project_id => @project} : params url_params = controller_name == 'issues' ? {:controller => 'issues', :action => 'index', :project_id => @project} : params
content_tag('h3', h(title)) + content_tag('h3', title) +
queries.collect {|query| queries.collect {|query|
link_to(h(query.name), url_params.merge(:query_id => query)) link_to(h(query.name), url_params.merge(:query_id => query))
}.join('<br />') }.join('<br />')
@@ -208,7 +206,7 @@ module IssuesHelper
unless no_html unless no_html
label = content_tag('strong', label) label = content_tag('strong', label)
old_value = content_tag("i", h(old_value)) if detail.old_value 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.blank? old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?)
if detail.property == 'attachment' && !value.blank? && a = Attachment.find_by_id(detail.prop_key) if detail.property == 'attachment' && !value.blank? && a = Attachment.find_by_id(detail.prop_key)
# Link to the attachment if it has not been removed # Link to the attachment if it has not been removed
value = link_to_attachment(a) value = link_to_attachment(a)
@@ -265,38 +263,59 @@ module IssuesHelper
end end
end end
def issues_to_csv(issues, project, query, options={}) def issues_to_csv(issues, project = nil)
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
decimal_separator = l(:general_csv_decimal_separator) decimal_separator = l(:general_csv_decimal_separator)
encoding = l(:general_csv_encoding)
columns = (options[:columns] == 'all' ? query.available_columns : query.columns)
export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv| export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
# csv header fields # csv header fields
csv << [ "#" ] + columns.collect {|c| Redmine::CodesetUtil.from_utf8(c.caption.to_s, encoding) } + headers = [ "#",
(options[:description] ? [Redmine::CodesetUtil.from_utf8(l(:field_description), encoding)] : []) l(:field_status),
l(:field_project),
l(:field_tracker),
l(:field_priority),
l(:field_subject),
l(:field_assigned_to),
l(:field_category),
l(:field_fixed_version),
l(:field_author),
l(:field_start_date),
l(:field_due_date),
l(:field_done_ratio),
l(:field_estimated_hours),
l(:field_parent_issue),
l(:field_created_on),
l(:field_updated_on)
]
# Export project custom fields if project is given
# otherwise export custom fields marked as "For all projects"
custom_fields = project.nil? ? IssueCustomField.for_all : project.all_issue_custom_fields
custom_fields.each {|f| headers << f.name}
# Description in the last column
headers << l(:field_description)
csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
# csv lines # csv lines
issues.each do |issue| issues.each do |issue|
col_values = columns.collect do |column| fields = [issue.id,
s = if column.is_a?(QueryCustomFieldColumn) issue.status.name,
cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id} issue.project.name,
show_value(cv) issue.tracker.name,
else issue.priority.name,
value = issue.send(column.name) issue.subject,
if value.is_a?(Date) issue.assigned_to,
format_date(value) issue.category,
elsif value.is_a?(Time) issue.fixed_version,
format_time(value) issue.author.name,
elsif value.is_a?(Float) format_date(issue.start_date),
value.to_s.gsub('.', decimal_separator) format_date(issue.due_date),
else issue.done_ratio,
value issue.estimated_hours.to_s.gsub('.', decimal_separator),
end issue.parent_id,
end format_time(issue.created_on),
s.to_s format_time(issue.updated_on)
end ]
csv << [ issue.id.to_s ] + col_values.collect {|c| Redmine::CodesetUtil.from_utf8(c.to_s, encoding) } + custom_fields.each {|f| fields << show_value(issue.custom_value_for(f)) }
(options[:description] ? [Redmine::CodesetUtil.from_utf8(issue.description, encoding)] : []) fields << issue.description
csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
end end
end end
export export
+6 -8
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006-2008 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -26,7 +24,7 @@ module JournalsHelper
links << link_to_remote(image_tag('comment.png'), links << link_to_remote(image_tag('comment.png'),
{ :url => {:controller => 'journals', :action => 'new', :id => issue, :journal_id => journal} }, { :url => {:controller => 'journals', :action => 'new', :id => issue, :journal_id => journal} },
:title => l(:button_quote)) if options[:reply_links] :title => l(:button_quote)) if options[:reply_links]
links << link_to_in_place_notes_editor(image_tag('edit.png'), "journal-#{journal.id}-notes", links << link_to_in_place_notes_editor(image_tag('edit.png'), "journal-#{journal.id}-notes",
{ :controller => 'journals', :action => 'edit', :id => journal }, { :controller => 'journals', :action => 'edit', :id => journal },
:title => l(:button_edit)) if editable :title => l(:button_edit)) if editable
end end
@@ -36,7 +34,7 @@ module JournalsHelper
css_classes << " editable" if editable css_classes << " editable" if editable
content_tag('div', content, :id => "journal-#{journal.id}-notes", :class => css_classes) content_tag('div', content, :id => "journal-#{journal.id}-notes", :class => css_classes)
end end
def link_to_in_place_notes_editor(text, field_id, url, options={}) def link_to_in_place_notes_editor(text, field_id, url, options={})
onclick = "new Ajax.Request('#{url_for(url)}', {asynchronous:true, evalScripts:true, method:'get'}); return false;" onclick = "new Ajax.Request('#{url_for(url)}', {asynchronous:true, evalScripts:true, method:'get'}); return false;"
link_to text, '#', options.merge(:onclick => onclick) link_to text, '#', options.merge(:onclick => onclick)
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006-2008 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006-2007 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+2 -4
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -48,7 +46,7 @@ module ProjectsHelper
options = '' options = ''
options << "<option value=''></option>" if project.allowed_parents.include?(nil) options << "<option value=''></option>" if project.allowed_parents.include?(nil)
options << project_tree_options_for_select(project.allowed_parents.compact, :selected => selected) options << project_tree_options_for_select(project.allowed_parents.compact, :selected => selected)
content_tag('select', options.html_safe, :name => 'project[parent_id]', :id => 'project_parent_id') content_tag('select', options, :name => 'project[parent_id]', :id => 'project_parent_id')
end end
# Renders a tree of projects as a nested set of unordered lists # Renders a tree of projects as a nested set of unordered lists
@@ -82,7 +80,7 @@ module ProjectsHelper
s << ("</li></ul>\n" * ancestors.size) s << ("</li></ul>\n" * ancestors.size)
@project = original_project @project = original_project
end end
s.html_safe s
end end
# Returns a set of options for a select field, grouped by project. # Returns a set of options for a select field, grouped by project.
+28 -33
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -7,31 +5,31 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module QueriesHelper module QueriesHelper
def operators_for_select(filter_type) def operators_for_select(filter_type)
Query.operators_by_filter_type[filter_type].collect {|o| [l(Query.operators[o]), o]} Query.operators_by_filter_type[filter_type].collect {|o| [l(Query.operators[o]), o]}
end end
def column_header(column) def column_header(column)
column.sortable ? sort_header_tag(column.name.to_s, :caption => column.caption, column.sortable ? sort_header_tag(column.name.to_s, :caption => column.caption,
:default_order => column.default_order) : :default_order => column.default_order) :
content_tag('th', h(column.caption)) content_tag('th', column.caption)
end end
def column_content(column, issue) def column_content(column, issue)
value = column.value(issue) value = column.value(issue)
case value.class.name case value.class.name
when 'String' when 'String'
if column.name == :subject if column.name == :subject
@@ -47,7 +45,7 @@ module QueriesHelper
if column.name == :done_ratio if column.name == :done_ratio
progress_bar(value, :width => '80px') progress_bar(value, :width => '80px')
else else
h(value.to_s) value.to_s
end end
when 'User' when 'User'
link_to_user value link_to_user value
@@ -76,30 +74,27 @@ module QueriesHelper
@query.project = @project @query.project = @project
session[:query] = {:id => @query.id, :project_id => @query.project_id} session[:query] = {:id => @query.id, :project_id => @query.project_id}
sort_clear sort_clear
elsif api_request? || params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
# Give it a name, required to be valid
@query = Query.new(:name => "_")
@query.project = @project
build_query_from_params
session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
else else
# retrieve from session if api_request? || params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
@query = Query.find_by_id(session[:query][:id]) if session[:query][:id] # Give it a name, required to be valid
@query ||= Query.new(:name => "_", :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names]) @query = Query.new(:name => "_")
@query.project = @project @query.project = @project
end if params[:fields] || params[:f]
end @query.filters = {}
@query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v])
def build_query_from_params else
if params[:fields] || params[:f] @query.available_filters.keys.each do |field|
@query.filters = {} @query.add_short_filter(field, params[field]) if params[field]
@query.add_filters(params[:fields] || params[:f], params[:operators] || params[:op], params[:values] || params[:v]) end
else end
@query.available_filters.keys.each do |field| @query.group_by = params[:group_by]
@query.add_short_filter(field, params[field]) if params[field] @query.column_names = params[:c] || (params[:query] && params[:query][:column_names])
session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
else
@query = Query.find_by_id(session[:query][:id]) if session[:query][:id]
@query ||= Query.new(:name => "_", :project => @project, :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names])
@query.project = @project
end end
end end
@query.group_by = params[:group_by] || (params[:query] && params[:query][:group_by])
@query.column_names = params[:c] || (params[:query] && params[:query][:column_names])
end end
end end
+1 -3
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -33,6 +31,6 @@ module ReportsHelper
def aggregate_link(data, criteria, *args) def aggregate_link(data, criteria, *args)
a = aggregate data, criteria a = aggregate data, criteria
a > 0 ? link_to(h(a), *args) : '-' a > 0 ? link_to(a, *args) : '-'
end end
end end
+47 -76
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -39,9 +37,9 @@ module RepositoriesHelper
unless properties.nil? || properties.empty? unless properties.nil? || properties.empty?
content = '' content = ''
properties.keys.sort.each do |property| properties.keys.sort.each do |property|
content << content_tag('li', "<b>#{h property}</b>: <span>#{h properties[property]}</span>".html_safe) content << content_tag('li', "<b>#{h property}</b>: <span>#{h properties[property]}</span>")
end end
content_tag('ul', content.html_safe, :class => 'properties') content_tag('ul', content, :class => 'properties')
end end
end end
@@ -89,7 +87,7 @@ module RepositoriesHelper
if s = tree[file][:s] if s = tree[file][:s]
style << ' folder' style << ' folder'
path_param = to_path_param(@repository.relative_path(file)) path_param = to_path_param(@repository.relative_path(file))
text = link_to(h(text), :controller => 'repositories', text = link_to(text, :controller => 'repositories',
:action => 'show', :action => 'show',
:id => @project, :id => @project,
:path => path_param, :path => path_param,
@@ -99,25 +97,56 @@ module RepositoriesHelper
elsif c = tree[file][:c] elsif c = tree[file][:c]
style << " change-#{c.action}" style << " change-#{c.action}"
path_param = to_path_param(@repository.relative_path(c.path)) path_param = to_path_param(@repository.relative_path(c.path))
text = link_to(h(text), :controller => 'repositories', text = link_to(text, :controller => 'repositories',
:action => 'entry', :action => 'entry',
:id => @project, :id => @project,
:path => path_param, :path => path_param,
:rev => @changeset.identifier) unless c.action == 'D' :rev => @changeset.identifier) unless c.action == 'D'
text << " - #{h(c.revision)}" unless c.revision.blank? text << " - #{c.revision}" unless c.revision.blank?
text << ' ('.html_safe + link_to(l(:label_diff), :controller => 'repositories', text << ' (' + link_to('diff', :controller => 'repositories',
:action => 'diff', :action => 'diff',
:id => @project, :id => @project,
:path => path_param, :path => path_param,
:rev => @changeset.identifier) + ') '.html_safe if c.action == 'M' :rev => @changeset.identifier) + ') ' if c.action == 'M'
text << ' '.html_safe + content_tag('span', h(c.from_path), :class => 'copied-from') unless c.from_path.blank? text << ' ' + content_tag('span', c.from_path, :class => 'copied-from') unless c.from_path.blank?
output << "<li class='#{style}'>#{text}</li>" output << "<li class='#{style}'>#{text}</li>"
end end
end end
output << '</ul>' output << '</ul>'
output.html_safe output
end end
def to_utf8(str)
return str if str.nil?
str = to_utf8_internal(str)
if str.respond_to?(:force_encoding)
str.force_encoding('UTF-8')
end
str
end
def to_utf8_internal(str)
return str if str.nil?
if str.respond_to?(:force_encoding)
str.force_encoding('ASCII-8BIT')
end
return str if str.empty?
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
if str.respond_to?(:force_encoding)
str.force_encoding('UTF-8')
end
@encodings ||= Setting.repositories_encodings.split(',').collect(&:strip)
@encodings.each do |encoding|
begin
return Iconv.conv('UTF-8', encoding, str)
rescue Iconv::Failure
# do nothing here and try the next encoding
end
end
str = Redmine::CodesetUtil.replace_invalid_utf8(str)
end
private :to_utf8_internal
def repository_field_tags(form, repository) def repository_field_tags(form, repository)
method = repository.class.name.demodulize.underscore + "_field_tags" method = repository.class.name.demodulize.underscore + "_field_tags"
if repository.is_a?(Repository) && if repository.is_a?(Repository) &&
@@ -159,8 +188,7 @@ module RepositoriesHelper
def subversion_field_tags(form, repository) def subversion_field_tags(form, repository)
content_tag('p', form.text_field(:url, :size => 60, :required => true, content_tag('p', form.text_field(:url, :size => 60, :required => true,
:disabled => (repository && !repository.root_url.blank?)) + :disabled => (repository && !repository.root_url.blank?)) +
'<br />'.html_safe + '<br />(file:///, http://, https://, svn://, svn+[tunnelscheme]://)') +
'(file:///, http://, https://, svn://, svn+[tunnelscheme]://)') +
content_tag('p', form.text_field(:login, :size => 30)) + content_tag('p', form.text_field(:login, :size => 30)) +
content_tag('p', form.password_field( content_tag('p', form.password_field(
:password, :size => 30, :name => 'ignore', :password, :size => 30, :name => 'ignore',
@@ -185,12 +213,12 @@ module RepositoriesHelper
:size => 60, :required => true, :size => 60, :required => true,
:disabled => (repository && !repository.root_url.blank?) :disabled => (repository && !repository.root_url.blank?)
) + ) +
'<br />'.html_safe + l(:text_mercurial_repository_note)) + '<br />' + l(:text_mercurial_repository_note)) +
content_tag('p', form.select( content_tag('p', form.select(
:path_encoding, [nil] + Setting::ENCODINGS, :path_encoding, [nil] + Setting::ENCODINGS,
:label => l(:field_scm_path_encoding) :label => l(:field_scm_path_encoding)
) + ) +
'<br />'.html_safe + l(:text_scm_path_encoding_note)) '<br />' + l(:text_scm_path_encoding_note))
end end
def git_field_tags(form, repository) def git_field_tags(form, repository)
@@ -199,13 +227,12 @@ module RepositoriesHelper
:size => 60, :required => true, :size => 60, :required => true,
:disabled => (repository && !repository.root_url.blank?) :disabled => (repository && !repository.root_url.blank?)
) + ) +
'<br />'.html_safe + '<br />' + l(:text_git_repository_note)) +
l(:text_git_repository_note)) +
content_tag('p', form.select( content_tag('p', form.select(
:path_encoding, [nil] + Setting::ENCODINGS, :path_encoding, [nil] + Setting::ENCODINGS,
:label => l(:field_scm_path_encoding) :label => l(:field_scm_path_encoding)
) + ) +
'<br />'.html_safe + l(:text_scm_path_encoding_note)) + '<br />' + l(:text_scm_path_encoding_note)) +
content_tag('p', form.check_box( content_tag('p', form.check_box(
:extra_report_last_commit, :extra_report_last_commit,
:label => l(:label_git_report_last_commit) :label => l(:label_git_report_last_commit)
@@ -230,7 +257,7 @@ module RepositoriesHelper
:path_encoding, [nil] + Setting::ENCODINGS, :path_encoding, [nil] + Setting::ENCODINGS,
:label => l(:field_scm_path_encoding) :label => l(:field_scm_path_encoding)
) + ) +
'<br />'.html_safe + l(:text_scm_path_encoding_note)) '<br />' + l(:text_scm_path_encoding_note))
end end
def bazaar_field_tags(form, repository) def bazaar_field_tags(form, repository)
@@ -252,62 +279,6 @@ module RepositoriesHelper
:path_encoding, [nil] + Setting::ENCODINGS, :path_encoding, [nil] + Setting::ENCODINGS,
:label => l(:field_scm_path_encoding) :label => l(:field_scm_path_encoding)
) + ) +
'<br />'.html_safe + l(:text_scm_path_encoding_note)) '<br />' + l(:text_scm_path_encoding_note))
end
def index_commits(commits, heads, href_proc = nil)
return nil if commits.nil? or commits.first.parents.nil?
map = {}
commit_hashes = []
refs_map = {}
href_proc ||= Proc.new {|x|x}
heads.each{|r| refs_map[r.scmid] ||= []; refs_map[r.scmid] << r}
commits.reverse.each_with_index do |c, i|
h = {}
h[:parents] = c.parents.collect do |p|
[p.scmid, 0, 0]
end
h[:rdmid] = i
h[:space] = 0
h[:refs] = refs_map[c.scmid].join(" ") if refs_map.include? c.scmid
h[:scmid] = c.scmid
h[:href] = href_proc.call(c.scmid)
commit_hashes << h
map[c.scmid] = h
end
heads.sort! do |a,b|
a.to_s <=> b.to_s
end
j = 0
heads.each do |h|
if map.include? h.scmid then
j = mark_chain(j += 1, map[h.scmid], map)
end
end
# when no head matched anything use first commit
if j == 0 then
mark_chain(j += 1, map.values.first, map)
end
map
end
def mark_chain(mark, commit, map)
stack = [[mark, commit]]
markmax = mark
until stack.empty?
current = stack.pop
m, commit = current
commit[:space] = m if commit[:space] == 0
m1 = m - 1
commit[:parents].each_with_index do |p, i|
psha = p[0]
if map.include? psha and map[psha][:space] == 0 then
stack << [m1 += 1, map[psha]] if i == 0
stack = [[m1 += 1, map[psha]]] + stack if i > 0
end
end
markmax = m1 if markmax < m1
end
markmax
end end
end end
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+7 -11
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -7,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -21,7 +19,7 @@ module SearchHelper
def highlight_tokens(text, tokens) def highlight_tokens(text, tokens)
return text unless text && tokens && !tokens.empty? return text unless text && tokens && !tokens.empty?
re_tokens = tokens.collect {|t| Regexp.escape(t)} re_tokens = tokens.collect {|t| Regexp.escape(t)}
regexp = Regexp.new "(#{re_tokens.join('|')})", Regexp::IGNORECASE regexp = Regexp.new "(#{re_tokens.join('|')})", Regexp::IGNORECASE
result = '' result = ''
text.split(regexp).each_with_index do |words, i| text.split(regexp).each_with_index do |words, i|
if result.length > 1200 if result.length > 1200
@@ -39,20 +37,19 @@ module SearchHelper
end end
result result
end end
def type_label(t) def type_label(t)
l("label_#{t.singularize}_plural", :default => t.to_s.humanize) l("label_#{t.singularize}_plural", :default => t.to_s.humanize)
end end
def project_select_tag def project_select_tag
options = [[l(:label_project_all), 'all']] options = [[l(:label_project_all), 'all']]
options << [l(:label_my_projects), 'my_projects'] unless User.current.memberships.empty? options << [l(:label_my_projects), 'my_projects'] unless User.current.memberships.empty?
options << [l(:label_and_its_subprojects, @project.name), 'subprojects'] unless @project.nil? || @project.descendants.active.empty? options << [l(:label_and_its_subprojects, @project.name), 'subprojects'] unless @project.nil? || @project.descendants.active.empty?
options << [@project.name, ''] unless @project.nil? options << [@project.name, ''] unless @project.nil?
label_tag("scope", l(:description_project_scope), :class => "hidden-for-sighted") +
select_tag('scope', options_for_select(options, params[:scope].to_s)) if options.size > 1 select_tag('scope', options_for_select(options, params[:scope].to_s)) if options.size > 1
end end
def render_results_by_type(results_by_type) def render_results_by_type(results_by_type)
links = [] links = []
# Sorts types by results count # Sorts types by results count
@@ -60,8 +57,7 @@ module SearchHelper
c = results_by_type[t] c = results_by_type[t]
next if c == 0 next if c == 0
text = "#{type_label(t)} (#{c})" text = "#{type_label(t)} (#{c})"
links << link_to(h(text), :q => params[:q], :titles_only => params[:titles_only], links << link_to(text, :q => params[:q], :titles_only => params[:titles_only], :all_words => params[:all_words], :scope => params[:scope], t => 1)
:all_words => params[:all_words], :scope => params[:scope], t => 1)
end end
('<ul>' + links.map {|link| content_tag('li', link)}.join(' ') + '</ul>') unless links.empty? ('<ul>' + links.map {|link| content_tag('li', link)}.join(' ') + '</ul>') unless links.empty?
end end
+16 -18
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -34,18 +32,18 @@ module SettingsHelper
if blank_text = options.delete(:blank) if blank_text = options.delete(:blank)
choices = [[blank_text.is_a?(Symbol) ? l(blank_text) : blank_text, '']] + choices choices = [[blank_text.is_a?(Symbol) ? l(blank_text) : blank_text, '']] + choices
end end
setting_label(setting, options).html_safe + setting_label(setting, options) +
select_tag("settings[#{setting}]", select_tag("settings[#{setting}]",
options_for_select(choices, Setting.send(setting).to_s), options_for_select(choices, Setting.send(setting).to_s),
options).html_safe options)
end end
def setting_multiselect(setting, choices, options={}) def setting_multiselect(setting, choices, options={})
setting_values = Setting.send(setting) setting_values = Setting.send(setting)
setting_values = [] unless setting_values.is_a?(Array) setting_values = [] unless setting_values.is_a?(Array)
setting_label(setting, options).html_safe + setting_label(setting, options) +
hidden_field_tag("settings[#{setting}][]", '').html_safe + hidden_field_tag("settings[#{setting}][]", '') +
choices.collect do |choice| choices.collect do |choice|
text, value = (choice.is_a?(Array) ? choice : [choice, choice]) text, value = (choice.is_a?(Array) ? choice : [choice, choice])
content_tag( content_tag(
@@ -57,28 +55,28 @@ module SettingsHelper
) + text.to_s, ) + text.to_s,
:class => 'block' :class => 'block'
) )
end.join.html_safe end.join
end end
def setting_text_field(setting, options={}) def setting_text_field(setting, options={})
setting_label(setting, options).html_safe + setting_label(setting, options) +
text_field_tag("settings[#{setting}]", Setting.send(setting), options).html_safe text_field_tag("settings[#{setting}]", Setting.send(setting), options)
end end
def setting_text_area(setting, options={}) def setting_text_area(setting, options={})
setting_label(setting, options).html_safe + setting_label(setting, options) +
text_area_tag("settings[#{setting}]", Setting.send(setting), options).html_safe text_area_tag("settings[#{setting}]", Setting.send(setting), options)
end end
def setting_check_box(setting, options={}) def setting_check_box(setting, options={})
setting_label(setting, options).html_safe + setting_label(setting, options) +
hidden_field_tag("settings[#{setting}]", 0).html_safe + hidden_field_tag("settings[#{setting}]", 0) +
check_box_tag("settings[#{setting}]", 1, Setting.send("#{setting}?"), options).html_safe check_box_tag("settings[#{setting}]", 1, Setting.send("#{setting}?"), options)
end end
def setting_label(setting, options={}) def setting_label(setting, options={})
label = options.delete(:label) label = options.delete(:label)
label != false ? content_tag("label", l(label || "setting_#{setting}")).html_safe : '' label != false ? content_tag("label", l(label || "setting_#{setting}")) : ''
end end
# Renders a notification field for a Redmine::Notifiable option # Renders a notification field for a Redmine::Notifiable option
@@ -86,8 +84,8 @@ module SettingsHelper
return content_tag(:label, return content_tag(:label,
check_box_tag('settings[notified_events][]', check_box_tag('settings[notified_events][]',
notifiable.name, notifiable.name,
Setting.notified_events.include?(notifiable.name)).html_safe + Setting.notified_events.include?(notifiable.name)) +
l_or_humanize(notifiable.name, :prefix => 'label_').html_safe, l_or_humanize(notifiable.name, :prefix => 'label_'),
:class => notifiable.parent.present? ? "parent" : '').html_safe :class => notifiable.parent.present? ? "parent" : '')
end end
end end
+26 -28
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Helpers to sort tables using clickable column headers. # Helpers to sort tables using clickable column headers.
# #
# Author: Stuart Rackham <srackham@methods.co.nz>, March 2005. # Author: Stuart Rackham <srackham@methods.co.nz>, March 2005.
@@ -17,18 +15,18 @@
# #
# helper :sort # helper :sort
# include SortHelper # include SortHelper
# #
# def list # def list
# sort_init 'last_name' # sort_init 'last_name'
# sort_update %w(first_name last_name) # sort_update %w(first_name last_name)
# @items = Contact.find_all nil, sort_clause # @items = Contact.find_all nil, sort_clause
# end # end
# #
# Controller (using Pagination module): # Controller (using Pagination module):
# #
# helper :sort # helper :sort
# include SortHelper # include SortHelper
# #
# def list # def list
# sort_init 'last_name' # sort_init 'last_name'
# sort_update %w(first_name last_name) # sort_update %w(first_name last_name)
@@ -36,9 +34,9 @@
# :order_by => sort_clause, # :order_by => sort_clause,
# :per_page => 10 # :per_page => 10
# end # end
# #
# View (table header in list.rhtml): # View (table header in list.rhtml):
# #
# <thead> # <thead>
# <tr> # <tr>
# <%= sort_header_tag('id', :title => 'Sort by contact ID') %> # <%= sort_header_tag('id', :title => 'Sort by contact ID') %>
@@ -54,32 +52,32 @@
module SortHelper module SortHelper
class SortCriteria class SortCriteria
def initialize def initialize
@criteria = [] @criteria = []
end end
def available_criteria=(criteria) def available_criteria=(criteria)
unless criteria.is_a?(Hash) unless criteria.is_a?(Hash)
criteria = criteria.inject({}) {|h,k| h[k] = k; h} criteria = criteria.inject({}) {|h,k| h[k] = k; h}
end end
@available_criteria = criteria @available_criteria = criteria
end end
def from_param(param) def from_param(param)
@criteria = param.to_s.split(',').collect {|s| s.split(':')[0..1]} @criteria = param.to_s.split(',').collect {|s| s.split(':')[0..1]}
normalize! normalize!
end end
def criteria=(arg) def criteria=(arg)
@criteria = arg @criteria = arg
normalize! normalize!
end end
def to_param def to_param
@criteria.collect {|k,o| k + (o ? '' : ':desc')}.join(',') @criteria.collect {|k,o| k + (o ? '' : ':desc')}.join(',')
end end
def to_sql def to_sql
sql = @criteria.collect do |k,o| sql = @criteria.collect do |k,o|
if s = @available_criteria[k] if s = @available_criteria[k]
@@ -88,33 +86,33 @@ module SortHelper
end.compact.join(', ') end.compact.join(', ')
sql.blank? ? nil : sql sql.blank? ? nil : sql
end end
def add!(key, asc) def add!(key, asc)
@criteria.delete_if {|k,o| k == key} @criteria.delete_if {|k,o| k == key}
@criteria = [[key, asc]] + @criteria @criteria = [[key, asc]] + @criteria
normalize! normalize!
end end
def add(*args) def add(*args)
r = self.class.new.from_param(to_param) r = self.class.new.from_param(to_param)
r.add!(*args) r.add!(*args)
r r
end end
def first_key def first_key
@criteria.first && @criteria.first.first @criteria.first && @criteria.first.first
end end
def first_asc? def first_asc?
@criteria.first && @criteria.first.last @criteria.first && @criteria.first.last
end end
def empty? def empty?
@criteria.empty? @criteria.empty?
end end
private private
def normalize! def normalize!
@criteria ||= [] @criteria ||= []
@criteria = @criteria.collect {|s| s = s.to_a; [s.first, (s.last == false || s.last == 'desc') ? false : true]} @criteria = @criteria.collect {|s| s = s.to_a; [s.first, (s.last == false || s.last == 'desc') ? false : true]}
@@ -122,7 +120,7 @@ module SortHelper
@criteria.slice!(3) @criteria.slice!(3)
self self
end end
# Appends DESC to the sort criterion unless it has a fixed order # Appends DESC to the sort criterion unless it has a fixed order
def append_desc(criterion) def append_desc(criterion)
if criterion =~ / (asc|desc)$/i if criterion =~ / (asc|desc)$/i
@@ -132,14 +130,14 @@ module SortHelper
end end
end end
end end
def sort_name def sort_name
controller_name + '_' + action_name + '_sort' controller_name + '_' + action_name + '_sort'
end end
# Initializes the default sort. # Initializes the default sort.
# Examples: # Examples:
# #
# sort_init 'name' # sort_init 'name'
# sort_init 'id', 'desc' # sort_init 'id', 'desc'
# sort_init ['name', ['id', 'desc']] # sort_init ['name', ['id', 'desc']]
@@ -167,7 +165,7 @@ module SortHelper
@sort_criteria.criteria = @sort_default if @sort_criteria.empty? @sort_criteria.criteria = @sort_default if @sort_criteria.empty?
session[sort_name] = @sort_criteria.to_param session[sort_name] = @sort_criteria.to_param
end end
# Clears the sort criteria session data # Clears the sort criteria session data
# #
def sort_clear def sort_clear
@@ -189,7 +187,7 @@ module SortHelper
# #
def sort_link(column, caption, default_order) def sort_link(column, caption, default_order)
css, order = nil, default_order css, order = nil, default_order
if column.to_s == @sort_criteria.first_key if column.to_s == @sort_criteria.first_key
if @sort_criteria.first_asc? if @sort_criteria.first_asc?
css = 'sort asc' css = 'sort asc'
@@ -200,14 +198,14 @@ module SortHelper
end end
end end
caption = column.to_s.humanize unless caption caption = column.to_s.humanize unless caption
sort_options = { :sort => @sort_criteria.add(column.to_s, order).to_param } sort_options = { :sort => @sort_criteria.add(column.to_s, order).to_param }
url_options = params.merge(sort_options) url_options = params.merge(sort_options)
# Add project_id to url_options # Add project_id to url_options
url_options = url_options.merge(:project_id => params[:project_id]) if params.has_key?(:project_id) url_options = url_options.merge(:project_id => params[:project_id]) if params.has_key?(:project_id)
link_to_content_update(h(caption), url_options, :class => css) link_to_content_update(caption, url_options, :class => css)
end end
# Returns a table header <th> tag with a sort link for the named column # Returns a table header <th> tag with a sort link for the named column
+31 -37
View File
@@ -1,25 +1,23 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module TimelogHelper module TimelogHelper
include ApplicationHelper include ApplicationHelper
def render_timelog_breadcrumb def render_timelog_breadcrumb
links = [] links = []
links << link_to(l(:label_project_all), {:project_id => nil, :issue_id => nil}) links << link_to(l(:label_project_all), {:project_id => nil, :issue_id => nil})
@@ -54,15 +52,15 @@ module TimelogHelper
activities.each { |a| collection << [a.name, a.id] } activities.each { |a| collection << [a.name, a.id] }
collection collection
end end
def select_hours(data, criteria, value) def select_hours(data, criteria, value)
if value.to_s.empty? if value.to_s.empty?
data.select {|row| row[criteria].blank? } data.select {|row| row[criteria].blank? }
else else
data.select {|row| row[criteria].to_s == value.to_s} data.select {|row| row[criteria].to_s == value.to_s}
end end
end end
def sum_hours(data) def sum_hours(data)
sum = 0 sum = 0
data.each do |row| data.each do |row|
@@ -70,7 +68,7 @@ module TimelogHelper
end end
sum sum
end end
def options_for_period_select(value) def options_for_period_select(value)
options_for_select([[l(:label_all_time), 'all'], options_for_select([[l(:label_all_time), 'all'],
[l(:label_today), 'today'], [l(:label_today), 'today'],
@@ -84,8 +82,9 @@ module TimelogHelper
[l(:label_this_year), 'current_year']], [l(:label_this_year), 'current_year']],
value) value)
end end
def entries_to_csv(entries) def entries_to_csv(entries)
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
decimal_separator = l(:general_csv_decimal_separator) decimal_separator = l(:general_csv_decimal_separator)
custom_fields = TimeEntryCustomField.find(:all) custom_fields = TimeEntryCustomField.find(:all)
export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv| export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
@@ -102,10 +101,8 @@ module TimelogHelper
] ]
# Export custom fields # Export custom fields
headers += custom_fields.collect(&:name) headers += custom_fields.collect(&:name)
csv << headers.collect {|c| Redmine::CodesetUtil.from_utf8( csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
c.to_s,
l(:general_csv_encoding) ) }
# csv lines # csv lines
entries.each do |entry| entries.each do |entry|
fields = [format_date(entry.spent_on), fields = [format_date(entry.spent_on),
@@ -119,15 +116,13 @@ module TimelogHelper
entry.comments entry.comments
] ]
fields += custom_fields.collect {|f| show_value(entry.custom_value_for(f)) } fields += custom_fields.collect {|f| show_value(entry.custom_value_for(f)) }
csv << fields.collect {|c| Redmine::CodesetUtil.from_utf8( csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
c.to_s,
l(:general_csv_encoding) ) }
end end
end end
export export
end end
def format_criteria_value(criteria, value) def format_criteria_value(criteria, value)
if value.blank? if value.blank?
l(:label_none) l(:label_none)
@@ -142,55 +137,54 @@ module TimelogHelper
format_value(value, @available_criterias[criteria][:format]) format_value(value, @available_criterias[criteria][:format])
end end
end end
def report_to_csv(criterias, periods, hours) def report_to_csv(criterias, periods, hours)
decimal_separator = l(:general_csv_decimal_separator)
export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv| export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
# Column headers # Column headers
headers = criterias.collect {|criteria| l(@available_criterias[criteria][:label]) } headers = criterias.collect {|criteria| l(@available_criterias[criteria][:label]) }
headers += periods headers += periods
headers << l(:label_total) headers << l(:label_total)
csv << headers.collect {|c| Redmine::CodesetUtil.from_utf8( csv << headers.collect {|c| to_utf8(c) }
c.to_s,
l(:general_csv_encoding) ) }
# Content # Content
report_criteria_to_csv(csv, criterias, periods, hours) report_criteria_to_csv(csv, criterias, periods, hours)
# Total row # Total row
str_total = Redmine::CodesetUtil.from_utf8(l(:label_total), l(:general_csv_encoding)) row = [ l(:label_total) ] + [''] * (criterias.size - 1)
row = [ str_total ] + [''] * (criterias.size - 1)
total = 0 total = 0
periods.each do |period| periods.each do |period|
sum = sum_hours(select_hours(hours, @columns, period.to_s)) sum = sum_hours(select_hours(hours, @columns, period.to_s))
total += sum total += sum
row << (sum > 0 ? ("%.2f" % sum).gsub('.',decimal_separator) : '') row << (sum > 0 ? "%.2f" % sum : '')
end end
row << ("%.2f" % total).gsub('.',decimal_separator) row << "%.2f" %total
csv << row csv << row
end end
export export
end end
def report_criteria_to_csv(csv, criterias, periods, hours, level=0) def report_criteria_to_csv(csv, criterias, periods, hours, level=0)
decimal_separator = l(:general_csv_decimal_separator)
hours.collect {|h| h[criterias[level]].to_s}.uniq.each do |value| hours.collect {|h| h[criterias[level]].to_s}.uniq.each do |value|
hours_for_value = select_hours(hours, criterias[level], value) hours_for_value = select_hours(hours, criterias[level], value)
next if hours_for_value.empty? next if hours_for_value.empty?
row = [''] * level row = [''] * level
row << Redmine::CodesetUtil.from_utf8( row << to_utf8(format_criteria_value(criterias[level], value))
format_criteria_value(criterias[level], value).to_s,
l(:general_csv_encoding) )
row += [''] * (criterias.length - level - 1) row += [''] * (criterias.length - level - 1)
total = 0 total = 0
periods.each do |period| periods.each do |period|
sum = sum_hours(select_hours(hours_for_value, @columns, period.to_s)) sum = sum_hours(select_hours(hours_for_value, @columns, period.to_s))
total += sum total += sum
row << (sum > 0 ? ("%.2f" % sum).gsub('.',decimal_separator) : '') row << (sum > 0 ? "%.2f" % sum : '')
end end
row << ("%.2f" % total).gsub('.',decimal_separator) row << "%.2f" %total
csv << row csv << row
if criterias.length > level + 1 if criterias.length > level + 1
report_criteria_to_csv(csv, criterias, periods, hours_for_value, level + 1) report_criteria_to_csv(csv, criterias, periods, hours_for_value, level + 1)
end end
end end
end end
def to_utf8(s)
@ic ||= Iconv.new(l(:general_csv_encoding), 'UTF-8')
begin; @ic.iconv(s.to_s); rescue; s.to_s; end
end
end end
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+10 -12
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -20,12 +18,12 @@
module UsersHelper module UsersHelper
def users_status_options_for_select(selected) def users_status_options_for_select(selected)
user_count_by_status = User.count(:group => 'status').to_hash user_count_by_status = User.count(:group => 'status').to_hash
options_for_select([[l(:label_all), ''], options_for_select([[l(:label_all), ''],
["#{l(:status_active)} (#{user_count_by_status[1].to_i})", 1], ["#{l(:status_active)} (#{user_count_by_status[1].to_i})", 1],
["#{l(:status_registered)} (#{user_count_by_status[2].to_i})", 2], ["#{l(:status_registered)} (#{user_count_by_status[2].to_i})", 2],
["#{l(:status_locked)} (#{user_count_by_status[3].to_i})", 3]], selected) ["#{l(:status_locked)} (#{user_count_by_status[3].to_i})", 3]], selected)
end end
# Options for the new membership projects combo-box # Options for the new membership projects combo-box
def options_for_membership_project_select(user, projects) def options_for_membership_project_select(user, projects)
options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---") options = content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---")
@@ -34,14 +32,14 @@ module UsersHelper
end end
options options
end end
def user_mail_notification_options(user) def user_mail_notification_options(user)
user.valid_notification_options.collect {|o| [l(o.last), o.first]} user.valid_notification_options.collect {|o| [l(o.last), o.first]}
end end
def change_status_link(user) def change_status_link(user)
url = {:controller => 'users', :action => 'update', :id => user, :page => params[:page], :status => params[:status], :tab => nil} url = {:controller => 'users', :action => 'update', :id => user, :page => params[:page], :status => params[:status], :tab => nil}
if user.locked? if user.locked?
link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock' link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock'
elsif user.registered? elsif user.registered?
@@ -50,7 +48,7 @@ module UsersHelper
link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :put, :class => 'icon icon-lock' link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :put, :class => 'icon icon-lock'
end end
end end
def user_settings_tabs def user_settings_tabs
tabs = [{:name => 'general', :partial => 'users/general', :label => :label_general}, tabs = [{:name => 'general', :partial => 'users/general', :label => :label_general},
{:name => 'memberships', :partial => 'users/memberships', :label => :label_project_plural} {:name => 'memberships', :partial => 'users/memberships', :label => :label_project_plural}
+6 -8
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -7,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -20,10 +18,10 @@
module VersionsHelper module VersionsHelper
STATUS_BY_CRITERIAS = %w(category tracker status priority author assigned_to) STATUS_BY_CRITERIAS = %w(category tracker status priority author assigned_to)
def render_issue_status_by(version, criteria) def render_issue_status_by(version, criteria)
criteria = 'category' unless STATUS_BY_CRITERIAS.include?(criteria) criteria = 'category' unless STATUS_BY_CRITERIAS.include?(criteria)
h = Hash.new {|k,v| k[v] = [0, 0]} h = Hash.new {|k,v| k[v] = [0, 0]}
begin begin
# Total issue count # Total issue count
@@ -38,10 +36,10 @@ module VersionsHelper
end end
counts = h.keys.compact.sort.collect {|k| {:group => k, :total => h[k][0], :open => h[k][1], :closed => (h[k][0] - h[k][1])}} counts = h.keys.compact.sort.collect {|k| {:group => k, :total => h[k][0], :open => h[k][1], :closed => (h[k][0] - h[k][1])}}
max = counts.collect {|c| c[:total]}.max max = counts.collect {|c| c[:total]}.max
render :partial => 'issue_counts', :locals => {:version => version, :criteria => criteria, :counts => counts, :max => max} render :partial => 'issue_counts', :locals => {:version => version, :criteria => criteria, :counts => counts, :max => max}
end end
def status_by_options_for_select(value) def status_by_options_for_select(value)
options_for_select(STATUS_BY_CRITERIAS.collect {|criteria| [l("field_#{criteria}".to_sym), criteria]}, value) options_for_select(STATUS_BY_CRITERIAS.collect {|criteria| [l("field_#{criteria}".to_sym), criteria]}, value)
end end
+7 -9
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -7,22 +5,22 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module WatchersHelper module WatchersHelper
def watcher_tag(object, user, options={}) def watcher_tag(object, user, options={})
content_tag("span", watcher_link(object, user), :class => watcher_css(object)) content_tag("span", watcher_link(object, user), :class => watcher_css(object))
end end
def watcher_link(object, user) def watcher_link(object, user)
return '' unless user && user.logged? && object.respond_to?('watched_by?') return '' unless user && user.logged? && object.respond_to?('watched_by?')
watched = object.watched_by?(user) watched = object.watched_by?(user)
@@ -34,14 +32,14 @@ module WatchersHelper
{:url => url}, {:url => url},
:href => url_for(url), :href => url_for(url),
:class => (watched ? 'icon icon-fav' : 'icon icon-fav-off')) :class => (watched ? 'icon icon-fav' : 'icon icon-fav-off'))
end end
# Returns the css class used to identify watch links for a given +object+ # Returns the css class used to identify watch links for a given +object+
def watcher_css(object) def watcher_css(object)
"#{object.class.to_s.underscore}-#{object.id}-watcher" "#{object.class.to_s.underscore}-#{object.id}-watcher"
end end
# Returns a comma separated list of users watching the given object # Returns a comma separated list of users watching the given object
def watchers_list(object) def watchers_list(object)
remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project) remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project)
+4 -6
View File
@@ -1,18 +1,16 @@
# encoding: utf-8 # redMine - project management software
# # Copyright (C) 2006 Jean-Philippe Lang
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+5 -13
View File
@@ -1,5 +1,3 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2011 Jean-Philippe Lang
# #
@@ -7,18 +5,18 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module WikiHelper module WikiHelper
def wiki_page_options_for_select(pages, selected = nil, parent = nil, level = 0) def wiki_page_options_for_select(pages, selected = nil, parent = nil, level = 0)
pages = pages.group_by(&:parent) unless pages.is_a?(Hash) pages = pages.group_by(&:parent) unless pages.is_a?(Hash)
s = '' s = ''
@@ -27,17 +25,11 @@ module WikiHelper
attrs = "value='#{page.id}'" attrs = "value='#{page.id}'"
attrs << " selected='selected'" if selected == page attrs << " selected='selected'" if selected == page
indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : nil indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : nil
s << "<option #{attrs}>#{indent}#{h page.pretty_title}</option>\n" + s << "<option #{attrs}>#{indent}#{h page.pretty_title}</option>\n" +
wiki_page_options_for_select(pages, selected, page, level + 1) wiki_page_options_for_select(pages, selected, page, level + 1)
end end
end end
s s
end end
def wiki_page_breadcrumb(page)
breadcrumb(page.ancestors.reverse.collect {|parent|
link_to(h(parent.pretty_title), {:controller => 'wiki', :action => 'show', :id => parent.title, :project_id => parent.project})
})
end
end end
+3 -5
View File
@@ -1,18 +1,16 @@
# encoding: utf-8
#
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2008 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+10 -20
View File
@@ -24,7 +24,6 @@ class Attachment < ActiveRecord::Base
validates_presence_of :container, :filename, :author validates_presence_of :container, :filename, :author
validates_length_of :filename, :maximum => 255 validates_length_of :filename, :maximum => 255
validates_length_of :disk_filename, :maximum => 255 validates_length_of :disk_filename, :maximum => 255
validate :validate_max_file_size
acts_as_event :title => :filename, acts_as_event :title => :filename,
:url => Proc.new {|o| {:controller => 'attachments', :action => 'download', :id => o.id, :filename => o.filename}} :url => Proc.new {|o| {:controller => 'attachments', :action => 'download', :id => o.id, :filename => o.filename}}
@@ -44,12 +43,9 @@ class Attachment < ActiveRecord::Base
"LEFT JOIN #{Project.table_name} ON #{Document.table_name}.project_id = #{Project.table_name}.id"} "LEFT JOIN #{Project.table_name} ON #{Document.table_name}.project_id = #{Project.table_name}.id"}
cattr_accessor :storage_path cattr_accessor :storage_path
@@storage_path = Redmine::Configuration['attachments_storage_path'] || "#{Rails.root}/files" @@storage_path = Redmine::Configuration['attachments_storage_path'] || "#{RAILS_ROOT}/files"
before_save :files_to_final_location def validate
after_destroy :delete_from_disk
def validate_max_file_size
if self.filesize > Setting.attachment_max_size.to_i.kilobytes if self.filesize > Setting.attachment_max_size.to_i.kilobytes
errors.add(:base, :too_long, :count => Setting.attachment_max_size.to_i.kilobytes) errors.add(:base, :too_long, :count => Setting.attachment_max_size.to_i.kilobytes)
end end
@@ -76,9 +72,9 @@ class Attachment < ActiveRecord::Base
# Copies the temporary file to its final location # Copies the temporary file to its final location
# and computes its MD5 hash # and computes its MD5 hash
def files_to_final_location def before_save
if @temp_file && (@temp_file.size > 0) if @temp_file && (@temp_file.size > 0)
logger.info("Saving attachment '#{self.diskfile}' (#{@temp_file.size} bytes)") logger.debug("saving '#{self.diskfile}'")
md5 = Digest::MD5.new md5 = Digest::MD5.new
File.open(diskfile, "wb") do |f| File.open(diskfile, "wb") do |f|
buffer = "" buffer = ""
@@ -89,7 +85,6 @@ class Attachment < ActiveRecord::Base
end end
self.digest = md5.hexdigest self.digest = md5.hexdigest
end end
@temp_file = nil
# Don't save the content type if it's longer than the authorized length # Don't save the content type if it's longer than the authorized length
if self.content_type && self.content_type.length > 255 if self.content_type && self.content_type.length > 255
self.content_type = nil self.content_type = nil
@@ -97,7 +92,7 @@ class Attachment < ActiveRecord::Base
end end
# Deletes file on the disk # Deletes file on the disk
def delete_from_disk def after_destroy
File.delete(diskfile) if !filename.blank? && File.exist?(diskfile) File.delete(diskfile) if !filename.blank? && File.exist?(diskfile)
end end
@@ -123,7 +118,7 @@ class Attachment < ActiveRecord::Base
end end
def image? def image?
self.filename =~ /\.(bmp|gif|jpg|jpe|jpeg|png)$/i self.filename =~ /\.(jpe?g|gif|png)$/i
end end
def is_text? def is_text?
@@ -154,7 +149,6 @@ class Attachment < ActiveRecord::Base
:file => file, :file => file,
:description => attachment['description'].to_s.strip, :description => attachment['description'].to_s.strip,
:author => User.current) :author => User.current)
obj.attachments << a
if a.new_record? if a.new_record?
obj.unsaved_attachments ||= [] obj.unsaved_attachments ||= []
@@ -167,19 +161,15 @@ class Attachment < ActiveRecord::Base
{:files => attached, :unsaved => obj.unsaved_attachments} {:files => attached, :unsaved => obj.unsaved_attachments}
end end
def self.latest_attach(attachments, filename)
attachments.sort_by(&:created_on).reverse.detect {
|att| att.filename.downcase == filename.downcase
}
end
private private
def sanitize_filename(value) def sanitize_filename(value)
# get only the filename, not the whole path # get only the filename, not the whole path
just_filename = value.gsub(/^.*(\\|\/)/, '') 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 invalid characters with underscore # Finally, replace all non alphanumeric, hyphens or periods with underscore
@filename = just_filename.gsub(/[\/\?\%\*\:\|\"\'<>]+/, '_') @filename = just_filename.gsub(/[^\w\.\-]/,'_')
end end
# Returns an ASCII or hashed filename # Returns an ASCII or hashed filename
+10 -10
View File
@@ -1,43 +1,43 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AuthSource < ActiveRecord::Base class AuthSource < ActiveRecord::Base
include Redmine::Ciphering include Redmine::Ciphering
has_many :users has_many :users
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name validates_uniqueness_of :name
validates_length_of :name, :maximum => 60 validates_length_of :name, :maximum => 60
def authenticate(login, password) def authenticate(login, password)
end end
def test_connection def test_connection
end end
def auth_method_name def auth_method_name
"Abstract" "Abstract"
end end
def account_password def account_password
read_ciphered_attribute(:account_password) read_ciphered_attribute(:account_password)
end end
def account_password=(arg) def account_password=(arg)
write_ciphered_attribute(:account_password, arg) write_ciphered_attribute(:account_password, arg)
end end
+19 -19
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -18,23 +18,23 @@
require 'net/ldap' require 'net/ldap'
require 'iconv' require 'iconv'
class AuthSourceLdap < AuthSource class AuthSourceLdap < AuthSource
validates_presence_of :host, :port, :attr_login validates_presence_of :host, :port, :attr_login
validates_length_of :name, :host, :maximum => 60, :allow_nil => true validates_length_of :name, :host, :maximum => 60, :allow_nil => true
validates_length_of :account, :account_password, :base_dn, :maximum => 255, :allow_nil => true validates_length_of :account, :account_password, :base_dn, :maximum => 255, :allow_nil => true
validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
validates_numericality_of :port, :only_integer => true validates_numericality_of :port, :only_integer => true
before_validation :strip_ldap_attributes before_validation :strip_ldap_attributes
def after_initialize def after_initialize
self.port = 389 if self.port == 0 self.port = 389 if self.port == 0
end end
def authenticate(login, password) def authenticate(login, password)
return nil if login.blank? || password.blank? return nil if login.blank? || password.blank?
attrs = get_user_dn(login) attrs = get_user_dn(login)
if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password) if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password)
logger.debug "Authentication successful for '#{login}'" if logger && logger.debug? logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
return attrs.except(:dn) return attrs.except(:dn)
@@ -50,19 +50,19 @@ class AuthSourceLdap < AuthSource
rescue Net::LDAP::LdapError => text rescue Net::LDAP::LdapError => text
raise "LdapError: " + text raise "LdapError: " + text
end end
def auth_method_name def auth_method_name
"LDAP" "LDAP"
end end
private private
def strip_ldap_attributes def strip_ldap_attributes
[:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr| [:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr|
write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil? write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil?
end end
end end
def initialize_ldap_con(ldap_user, ldap_password) def initialize_ldap_con(ldap_user, ldap_password)
options = { :host => self.host, options = { :host => self.host,
:port => self.port, :port => self.port,
@@ -102,12 +102,12 @@ class AuthSourceLdap < AuthSource
# Get the user's dn and any attributes for them, given their login # Get the user's dn and any attributes for them, given their login
def get_user_dn(login) def get_user_dn(login)
ldap_con = initialize_ldap_con(self.account, self.account_password) ldap_con = initialize_ldap_con(self.account, self.account_password)
login_filter = Net::LDAP::Filter.eq( self.attr_login, login ) login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
object_filter = Net::LDAP::Filter.eq( "objectClass", "*" ) object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
attrs = {} attrs = {}
ldap_con.search( :base => self.base_dn, ldap_con.search( :base => self.base_dn,
:filter => object_filter & login_filter, :filter => object_filter & login_filter,
:attributes=> search_attributes) do |entry| :attributes=> search_attributes) do |entry|
if onthefly_register? if onthefly_register?
@@ -121,7 +121,7 @@ class AuthSourceLdap < AuthSource
attrs attrs
end end
def self.get_attr(entry, attr_name) def self.get_attr(entry, attr_name)
if !attr_name.blank? if !attr_name.blank?
entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name] entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
+9 -15
View File
@@ -1,50 +1,44 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Board < ActiveRecord::Base class Board < ActiveRecord::Base
include Redmine::SafeAttributes
belongs_to :project belongs_to :project
has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC" has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC"
has_many :messages, :dependent => :destroy, :order => "#{Message.table_name}.created_on DESC" has_many :messages, :dependent => :destroy, :order => "#{Message.table_name}.created_on DESC"
belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id
acts_as_list :scope => :project_id acts_as_list :scope => :project_id
acts_as_watchable acts_as_watchable
validates_presence_of :name, :description validates_presence_of :name, :description
validates_length_of :name, :maximum => 30 validates_length_of :name, :maximum => 30
validates_length_of :description, :maximum => 255 validates_length_of :description, :maximum => 255
named_scope :visible, lambda {|*args| { :include => :project,
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_messages, *args) } }
safe_attributes 'name', 'description', 'move_to'
def visible?(user=User.current) def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_messages, project) !user.nil? && user.allowed_to?(:view_messages, project)
end end
def to_s def to_s
name name
end end
def reset_counters! def reset_counters!
self.class.reset_counters!(id) self.class.reset_counters!(id)
end end
# Updates topics_count, messages_count and last_message_id attributes for +board_id+ # Updates topics_count, messages_count and last_message_id attributes for +board_id+
def self.reset_counters!(board_id) def self.reset_counters!(board_id)
board_id = board_id.to_i board_id = board_id.to_i
+1 -2
View File
@@ -20,13 +20,12 @@ class Change < ActiveRecord::Base
validates_presence_of :changeset_id, :action, :path validates_presence_of :changeset_id, :action, :path
before_save :init_path before_save :init_path
before_validation :replace_invalid_utf8_of_path
def relative_path def relative_path
changeset.repository.relative_path(path) changeset.repository.relative_path(path)
end end
def replace_invalid_utf8_of_path def before_validation
self.path = Redmine::CodesetUtil.replace_invalid_utf8(self.path) self.path = Redmine::CodesetUtil.replace_invalid_utf8(self.path)
self.from_path = Redmine::CodesetUtil.replace_invalid_utf8(self.from_path) self.from_path = Redmine::CodesetUtil.replace_invalid_utf8(self.from_path)
end end
+40 -22
View File
@@ -22,14 +22,6 @@ class Changeset < ActiveRecord::Base
belongs_to :user belongs_to :user
has_many :changes, :dependent => :delete_all has_many :changes, :dependent => :delete_all
has_and_belongs_to_many :issues has_and_belongs_to_many :issues
has_and_belongs_to_many :parents,
:class_name => "Changeset",
:join_table => "#{table_name_prefix}changeset_parents#{table_name_suffix}",
:association_foreign_key => 'parent_id', :foreign_key => 'changeset_id'
has_and_belongs_to_many :children,
:class_name => "Changeset",
:join_table => "#{table_name_prefix}changeset_parents#{table_name_suffix}",
:association_foreign_key => 'changeset_id', :foreign_key => 'parent_id'
acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.format_identifier}" + (o.short_comments.blank? ? '' : (': ' + o.short_comments))}, acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.format_identifier}" + (o.short_comments.blank? ? '' : (': ' + o.short_comments))},
:description => :long_comments, :description => :long_comments,
@@ -52,9 +44,6 @@ class Changeset < ActiveRecord::Base
named_scope :visible, lambda {|*args| { :include => {:repository => :project}, named_scope :visible, lambda {|*args| { :include => {:repository => :project},
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args) } } :conditions => Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args) } }
after_create :scan_for_issues
before_create :before_create_cs
def revision=(r) def revision=(r)
write_attribute :revision, (r.nil? ? nil : r.to_s) write_attribute :revision, (r.nil? ? nil : r.to_s)
end end
@@ -90,14 +79,14 @@ class Changeset < ActiveRecord::Base
user || committer.to_s.split('<').first user || committer.to_s.split('<').first
end end
def before_create_cs def before_create
self.committer = self.class.to_utf8(self.committer, repository.repo_log_encoding) self.committer = self.class.to_utf8(self.committer, repository.repo_log_encoding)
self.comments = self.class.normalize_comments( self.comments = self.class.normalize_comments(
self.comments, repository.repo_log_encoding) self.comments, repository.repo_log_encoding)
self.user = repository.find_committer_user(self.committer) self.user = repository.find_committer_user(self.committer)
end end
def scan_for_issues def after_create
scan_comment_for_issue_ids scan_comment_for_issue_ids
end end
@@ -151,16 +140,12 @@ class Changeset < ActiveRecord::Base
@long_comments || split_comments.last @long_comments || split_comments.last
end end
def text_tag(ref_project=nil) def text_tag
tag = if scmid? if scmid?
"commit:#{scmid}" "commit:#{scmid}"
else else
"r#{revision}" "r#{revision}"
end end
if ref_project && project && ref_project != project
tag = "#{project.identifier}:#{tag}"
end
tag
end end
# Returns the previous changeset # Returns the previous changeset
@@ -217,7 +202,7 @@ class Changeset < ActiveRecord::Base
# don't change the status is the issue is closed # don't change the status is the issue is closed
return if issue.status && issue.status.is_closed? return if issue.status && issue.status.is_closed?
journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, text_tag(issue.project))) journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, text_tag))
issue.status = status issue.status = status
unless Setting.commit_fix_done_ratio.blank? unless Setting.commit_fix_done_ratio.blank?
issue.done_ratio = Setting.commit_fix_done_ratio.to_i issue.done_ratio = Setting.commit_fix_done_ratio.to_i
@@ -236,7 +221,7 @@ class Changeset < ActiveRecord::Base
:hours => hours, :hours => hours,
:issue => issue, :issue => issue,
:spent_on => commit_date, :spent_on => commit_date,
:comments => l(:text_time_logged_by_changeset, :value => text_tag(issue.project), :comments => l(:text_time_logged_by_changeset, :value => text_tag,
:locale => Setting.default_language) :locale => Setting.default_language)
) )
time_entry.activity = log_time_activity unless log_time_activity.nil? time_entry.activity = log_time_activity unless log_time_activity.nil?
@@ -268,6 +253,39 @@ class Changeset < ActiveRecord::Base
end end
def self.to_utf8(str, encoding) def self.to_utf8(str, encoding)
Redmine::CodesetUtil.to_utf8(str, encoding) return str if str.nil?
str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
if str.empty?
str.force_encoding("UTF-8") if str.respond_to?(:force_encoding)
return str
end
enc = encoding.blank? ? "UTF-8" : encoding
if str.respond_to?(:force_encoding)
if enc.upcase != "UTF-8"
str.force_encoding(enc)
str = str.encode("UTF-8", :invalid => :replace,
:undef => :replace, :replace => '?')
else
str.force_encoding("UTF-8")
if ! str.valid_encoding?
str = str.encode("US-ASCII", :invalid => :replace,
:undef => :replace, :replace => '?').encode("UTF-8")
end
end
else
ic = Iconv.new('UTF-8', enc)
txtar = ""
begin
txtar += ic.iconv(str)
rescue Iconv::IllegalSequence
txtar += $!.success
str = '?' + $!.failed[1,$!.failed.length]
retry
rescue
txtar += $!.success
end
str = txtar
end
str
end end
end end
+4 -7
View File
@@ -1,26 +1,23 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Comment < ActiveRecord::Base class Comment < ActiveRecord::Base
include Redmine::SafeAttributes
belongs_to :commented, :polymorphic => true, :counter_cache => true belongs_to :commented, :polymorphic => true, :counter_cache => true
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
validates_presence_of :commented, :author, :comments validates_presence_of :commented, :author, :comments
safe_attributes 'comments'
end end
+2 -2
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+18 -20
View File
@@ -5,12 +5,12 @@
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -19,31 +19,29 @@ class CustomField < ActiveRecord::Base
has_many :custom_values, :dependent => :delete_all has_many :custom_values, :dependent => :delete_all
acts_as_list :scope => 'type = \'#{self.class}\'' acts_as_list :scope => 'type = \'#{self.class}\''
serialize :possible_values serialize :possible_values
validates_presence_of :name, :field_format validates_presence_of :name, :field_format
validates_uniqueness_of :name, :scope => :type validates_uniqueness_of :name, :scope => :type
validates_length_of :name, :maximum => 30 validates_length_of :name, :maximum => 30
validates_inclusion_of :field_format, :in => Redmine::CustomFieldFormat.available_formats validates_inclusion_of :field_format, :in => Redmine::CustomFieldFormat.available_formats
validate :validate_values
def initialize(attributes = nil) def initialize(attributes = nil)
super super
self.possible_values ||= [] self.possible_values ||= []
end end
def before_validation def before_validation
# make sure these fields are not searchable # make sure these fields are not searchable
self.searchable = false if %w(int float date bool).include?(field_format) self.searchable = false if %w(int float date bool).include?(field_format)
true true
end end
def validate_values def validate
if self.field_format == "list" if self.field_format == "list"
errors.add(:possible_values, :blank) if self.possible_values.nil? || self.possible_values.empty? errors.add(:possible_values, :blank) if self.possible_values.nil? || self.possible_values.empty?
errors.add(:possible_values, :invalid) unless self.possible_values.is_a? Array errors.add(:possible_values, :invalid) unless self.possible_values.is_a? Array
end end
if regexp.present? if regexp.present?
begin begin
Regexp.new(regexp) Regexp.new(regexp)
@@ -51,13 +49,13 @@ class CustomField < ActiveRecord::Base
errors.add(:regexp, :invalid) errors.add(:regexp, :invalid)
end end
end end
# validate default value # validate default value
v = CustomValue.new(:custom_field => self.clone, :value => default_value, :customized => nil) v = CustomValue.new(:custom_field => self.clone, :value => default_value, :customized => nil)
v.custom_field.is_required = false v.custom_field.is_required = false
errors.add(:default_value, :invalid) unless v.valid? errors.add(:default_value, :invalid) unless v.valid?
end end
def possible_values_options(obj=nil) def possible_values_options(obj=nil)
case field_format case field_format
when 'user', 'version' when 'user', 'version'
@@ -77,7 +75,7 @@ class CustomField < ActiveRecord::Base
read_attribute :possible_values read_attribute :possible_values
end end
end end
def possible_values(obj=nil) def possible_values(obj=nil)
case field_format case field_format
when 'user', 'version' when 'user', 'version'
@@ -86,7 +84,7 @@ class CustomField < ActiveRecord::Base
read_attribute :possible_values read_attribute :possible_values
end end
end end
# Makes possible_values accept a multiline string # Makes possible_values accept a multiline string
def possible_values=(arg) def possible_values=(arg)
if arg.is_a?(Array) if arg.is_a?(Array)
@@ -95,7 +93,7 @@ class CustomField < ActiveRecord::Base
self.possible_values = arg.to_s.split(/[\n\r]+/) self.possible_values = arg.to_s.split(/[\n\r]+/)
end end
end end
def cast_value(value) def cast_value(value)
casted = nil casted = nil
unless value.blank? unless value.blank?
@@ -116,7 +114,7 @@ class CustomField < ActiveRecord::Base
end end
casted casted
end end
# Returns a ORDER BY clause that can used to sort customized # Returns a ORDER BY clause that can used to sort customized
# objects by their value of the custom field. # objects by their value of the custom field.
# Returns false, if the custom field can not be used for sorting. # Returns false, if the custom field can not be used for sorting.
@@ -124,7 +122,7 @@ class CustomField < ActiveRecord::Base
case field_format case field_format
when 'string', 'text', 'list', 'date', 'bool' when 'string', 'text', 'list', 'date', 'bool'
# COALESCE is here to make sure that blank and NULL values are sorted equally # COALESCE is here to make sure that blank and NULL values are sorted equally
"COALESCE((SELECT cv_sort.value FROM #{CustomValue.table_name} cv_sort" + "COALESCE((SELECT cv_sort.value FROM #{CustomValue.table_name} cv_sort" +
" WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" + " WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" +
" AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" + " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
" AND cv_sort.custom_field_id=#{id} LIMIT 1), '')" " AND cv_sort.custom_field_id=#{id} LIMIT 1), '')"
@@ -132,7 +130,7 @@ class CustomField < ActiveRecord::Base
# Make the database cast values into numeric # Make the database cast values into numeric
# Postgresql will raise an error if a value can not be casted! # Postgresql will raise an error if a value can not be casted!
# CustomValue validations should ensure that it doesn't occur # CustomValue validations should ensure that it doesn't occur
"(SELECT CAST(cv_sort.value AS decimal(60,3)) FROM #{CustomValue.table_name} cv_sort" + "(SELECT CAST(cv_sort.value AS decimal(60,3)) FROM #{CustomValue.table_name} cv_sort" +
" WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" + " WHERE cv_sort.customized_type='#{self.class.customized_class.name}'" +
" AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" + " AND cv_sort.customized_id=#{self.class.customized_class.table_name}.id" +
" AND cv_sort.custom_field_id=#{id} AND cv_sort.value <> '' AND cv_sort.value IS NOT NULL LIMIT 1)" " AND cv_sort.custom_field_id=#{id} AND cv_sort.value <> '' AND cv_sort.value IS NOT NULL LIMIT 1)"
@@ -144,17 +142,17 @@ class CustomField < ActiveRecord::Base
def <=>(field) def <=>(field)
position <=> field.position position <=> field.position
end end
def self.customized_class def self.customized_class
self.name =~ /^(.+)CustomField$/ self.name =~ /^(.+)CustomField$/
begin; $1.constantize; rescue nil; end begin; $1.constantize; rescue nil; end
end end
# to move in project_custom_field # to move in project_custom_field
def self.for_all def self.for_all
find(:all, :conditions => ["is_for_all=?", true], :order => 'position') find(:all, :conditions => ["is_for_all=?", true], :order => 'position')
end end
def type_name def type_name
nil nil
end end
+13 -15
View File
@@ -1,16 +1,16 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -19,44 +19,42 @@ class CustomValue < ActiveRecord::Base
belongs_to :custom_field belongs_to :custom_field
belongs_to :customized, :polymorphic => true belongs_to :customized, :polymorphic => true
validate :validate_custom_value
def after_initialize def after_initialize
if new_record? && custom_field && (customized_type.blank? || (customized && customized.new_record?)) if new_record? && custom_field && (customized_type.blank? || (customized && customized.new_record?))
self.value ||= custom_field.default_value self.value ||= custom_field.default_value
end end
end end
# Returns true if the boolean custom value is true # Returns true if the boolean custom value is true
def true? def true?
self.value == '1' self.value == '1'
end end
def editable? def editable?
custom_field.editable? custom_field.editable?
end end
def visible? def visible?
custom_field.visible? custom_field.visible?
end end
def required? def required?
custom_field.is_required? custom_field.is_required?
end end
def to_s def to_s
value.to_s value.to_s
end end
protected protected
def validate_custom_value def validate
if value.blank? if value.blank?
errors.add(:value, :blank) if custom_field.is_required? and value.blank? errors.add(:value, :blank) if custom_field.is_required? and value.blank?
else else
errors.add(:value, :invalid) unless custom_field.regexp.blank? or value =~ Regexp.new(custom_field.regexp) errors.add(:value, :invalid) unless custom_field.regexp.blank? or value =~ Regexp.new(custom_field.regexp)
errors.add(:value, :too_short, :count => custom_field.min_length) if custom_field.min_length > 0 and value.length < custom_field.min_length errors.add(:value, :too_short, :count => custom_field.min_length) if custom_field.min_length > 0 and value.length < custom_field.min_length
errors.add(:value, :too_long, :count => custom_field.max_length) if custom_field.max_length > 0 and value.length > custom_field.max_length errors.add(:value, :too_long, :count => custom_field.max_length) if custom_field.max_length > 0 and value.length > custom_field.max_length
# Format specific validations # Format specific validations
case custom_field.field_format case custom_field.field_format
when 'int' when 'int'
-3
View File
@@ -16,7 +16,6 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Document < ActiveRecord::Base class Document < ActiveRecord::Base
include Redmine::SafeAttributes
belongs_to :project belongs_to :project
belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id" belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
acts_as_attachable :delete_permission => :manage_documents acts_as_attachable :delete_permission => :manage_documents
@@ -33,8 +32,6 @@ class Document < ActiveRecord::Base
named_scope :visible, lambda {|*args| { :include => :project, named_scope :visible, lambda {|*args| { :include => :project,
:conditions => Project.allowed_to_condition(args.shift || User.current, :view_documents, *args) } } :conditions => Project.allowed_to_condition(args.shift || User.current, :view_documents, *args) } }
safe_attributes 'category_id', 'title', 'description'
def visible?(user=User.current) def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_documents, project) !user.nil? && user.allowed_to?(:view_documents, project)
end end
+17 -18
View File
@@ -1,32 +1,31 @@
# Redmine - project management software # redMine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Enumeration < ActiveRecord::Base class Enumeration < ActiveRecord::Base
default_scope :order => "#{Enumeration.table_name}.position ASC" default_scope :order => "#{Enumeration.table_name}.position ASC"
belongs_to :project belongs_to :project
acts_as_list :scope => 'type = \'#{type}\'' acts_as_list :scope => 'type = \'#{type}\''
acts_as_customizable acts_as_customizable
acts_as_tree :order => 'position ASC' acts_as_tree :order => 'position ASC'
before_destroy :check_integrity before_destroy :check_integrity
before_save :check_default
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name, :scope => [:type, :project_id] validates_uniqueness_of :name, :scope => [:type, :project_id]
validates_length_of :name, :maximum => 30 validates_length_of :name, :maximum => 30
@@ -46,23 +45,23 @@ class Enumeration < ActiveRecord::Base
find(:first, :conditions => { :is_default => true }) find(:first, :conditions => { :is_default => true })
end end
end end
# Overloaded on concrete classes # Overloaded on concrete classes
def option_name def option_name
nil nil
end end
def check_default def before_save
if is_default? && is_default_changed? if is_default? && is_default_changed?
Enumeration.update_all("is_default = #{connection.quoted_false}", {:type => type}) Enumeration.update_all("is_default = #{connection.quoted_false}", {:type => type})
end end
end end
# Overloaded on concrete classes # Overloaded on concrete classes
def objects_count def objects_count
0 0
end end
def in_use? def in_use?
self.objects_count != 0 self.objects_count != 0
end end
@@ -71,9 +70,9 @@ class Enumeration < ActiveRecord::Base
def is_override? def is_override?
!self.parent.nil? !self.parent.nil?
end end
alias :destroy_without_reassign :destroy alias :destroy_without_reassign :destroy
# Destroy the enumeration # Destroy the enumeration
# If a enumeration is specified, objects are reassigned # If a enumeration is specified, objects are reassigned
def destroy(reassign_to = nil) def destroy(reassign_to = nil)
@@ -82,11 +81,11 @@ class Enumeration < ActiveRecord::Base
end end
destroy_without_reassign destroy_without_reassign
end end
def <=>(enumeration) def <=>(enumeration)
position <=> enumeration.position position <=> enumeration.position
end end
def to_s; name end def to_s; name end
# Returns the Subclasses of Enumeration. Each Subclass needs to be # Returns the Subclasses of Enumeration. Each Subclass needs to be
@@ -116,13 +115,13 @@ class Enumeration < ActiveRecord::Base
return true return true
end end
# Are the new and previous fields equal? # Are the new and previous fields equal?
def self.same_active_state?(new, previous) def self.same_active_state?(new, previous)
new = (new == "1" ? true : false) new = (new == "1" ? true : false)
return new == previous return new == previous
end end
private private
def check_integrity def check_integrity
raise "Can't delete enumeration" if self.in_use? raise "Can't delete enumeration" if self.in_use?

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