рдЕрдкрдиреА рдкрд┐рдЫрд▓реА рдкреЛрд╕реНрдЯ рдореЗрдВ рдореИрдВрдиреЗ рд▓рд┐рдирдХреНрд╕ рдЙрдмрдВрдЯреВ рдореЗрдВ рд░реЗрдбрдорд╛рдЗрди рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рд╕рднреА рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХрд╛ рдкрд░реНрдпрд╛рдкреНрдд рд╡рд┐рд╡рд░рдг рджреЗрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреАред рдЗрд╕рдореЗрдВ, рдореИрдВ Redmine рдХреЗ рд▓рд┐рдП рдкреНрд▓рдЧрдЗрдиреНрд╕ рд▓рд┐рдЦрдиреЗ рдХреА рдкреЗрдЪреАрджрдЧрд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдорд╛рдирдХ Redmine рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдореБрдЦреНрдп рд╕рдВрднрд╛рд╡рдирд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рдореЗрд░реА рдЯреАрдо рдХреЛ рд░рд╛рд╕реНрддреЗ рдореЗрдВ рдорд┐рд▓реЗ рдиреБрдХрд╕рд╛рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВред
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд▓реЗрдЦ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛, рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд░реВрдмреА рдХреА рд░реВрдкрд░реЗрдЦрд╛ рдкрд░ рд░реВрдмреА рдХреА рдмреБрдирд┐рдпрд╛рджреА рдмрд╛рддреЛрдВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВ рдФрд░ рд░реЗрдбрдорд╛рдЗрди рдХреЗ рд▓рд┐рдП рдкреНрд▓рдЧрдЗрдиреНрд╕ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣ рд╕рднреА Redmine рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХреЛ рджреЛ рд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реИ:
рдкрд╣рд▓реЗ рдореЗрдВ рд╡реЗ рдкреНрд▓рдЧрдЗрдиреНрд╕ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдорд╛рдирдХ рд░реЗрдбрдорд╛рдЗрди рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпреЗ Redmine рдХреЗ рдЕрдВрджрд░ рд╕рд╛рдзрд╛рд░рдг рд░реЗрд▓ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╣реИрдВ, рдЙрдирдХреЗ рд╕рд╛рде рдХреБрдЫ рдХрдард┐рдирд╛рдЗрдпрд╛рдВ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╡реЗ рдмрд╣реБрдд рдХрдо рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВред рдЖрдзрд┐рдХрд╛рд░рд┐рдХ Redmine рд╡реЗрдмрд╕рд╛рдЗрдЯ рдореЗрдВ рдПрдХ
рдЕрдЪреНрдЫрд╛ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рд╣реИ рдЬреЛ рд╡рд┐рд╡рд░рдг рджреЗрддрд╛ рд╣реИ рдХрд┐ рдорддрджрд╛рди рдкреНрд▓рдЧрдЗрди рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдП ред
рд╕рдм рдХреБрдЫ рдереЛрдбрд╝рд╛ рдФрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ рдЬрдм рдкреНрд▓рдЧрдЗрди рдХреЛ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ!
рдЖрдЗрдП рдЙрд╕ рдЯреАрдо рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ рдЬреЛ Redmine рдкреНрд▓рдЧрдЗрди рдХреЗ рд▓рд┐рдП рдлрд╝реЛрд▓реНрдбрд░ рд╕рдВрд░рдЪрдирд╛ рдмрдирд╛рддреА рд╣реИред рд╣рдорд╛рд░реЗ рдкреНрд▓рдЧрдЗрди рдХреЛ рд▓рдХреНрдЬрд╝рд░реА рдмрдЯрди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред Redmine рдХреЗ рд░реВрдЯ рдлреЛрд▓реНрдбрд░ рдореЗрдВ рдЬрд╛рдПрдВ, рдХрдорд╛рдВрдб рдХреЛ рд░рди рдХрд░реЗрдВ рдЬреЛ рдлреЛрд▓реНрдбрд░ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдмрдирд╛рддрд╛ рд╣реИ:
$cd /usr/share/srv-redmine/redmine-2.3 $rails generate redmine_plugin LuxuryButtons
рдХрдорд╛рдВрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, Luxury_buttons рдлрд╝реЛрд▓реНрдбрд░ рдХреЛ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдирд┐рдореНрди рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд╕рд╛рде рджрд┐рдЦрд╛рдИ рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП:

Lib рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ, рдЖрдкрдХреЛ рддреБрд░рдВрдд рдПрдХ рдлрд╝реЛрд▓реНрдбрд░ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдкреНрд▓рдЧрдЗрди рдХреЗ рдирд╛рдо рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рддред Luxury_buttons рдлрд╝реЛрд▓реНрдбрд░ (рдмрд╛рдж рдореЗрдВ рдкреИрдЪ
рдлрд╝реЛрд▓реНрдбрд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрджрд░реНрднрд┐рдд)ред рдЗрд╕ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ, рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рд╡рд┐рднрд┐рдиреНрди рд░реЗрдбрдорд╛рдЗрди рд╡рд┐рдзрд┐рдпреЛрдВ рдХреА рдкреИрдЪ рдлрд╛рдЗрд▓реЗрдВ рд╣реЛрдВрдЧреАред
рдкреНрд▓рдЧрдЗрди рдХрд╣рддреЗ рд╣реА рд╣рдордиреЗ рдЗрд╕ рдлреЛрд▓реНрдбрд░ рдХрд╛ рдирд╛рдо рдХреНрдпреЛрдВ рд░рдЦрд╛? рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рд╕рд┐рдлрд╛рд░рд┐рд╢ рд╣реИ, рдлрд╝реЛрд▓реНрдбрд░ рдХреЛ рдЕрд▓рдЧ рддрд░рд╣ рд╕реЗ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рдкрд╣рд▓рд╛ рдиреБрдХрд╕рд╛рди рд╣реЛрддрд╛ рд╣реИ: рдпрджрд┐ рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд▓рдЧрдЗрди рдореЗрдВ рдЗрд╕ рдлрд╝реЛрд▓реНрдбрд░ рдХрд╛ рдирд╛рдо рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ рдФрд░ рдкреИрдЪ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ, рддреЛ рдкреИрдЪ рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдмрд╕ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ! рдЗрд╕рд▓рд┐рдП, рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ рдХрд┐ рдЖрдк
рдкреИрдЪ рдлрд╝реЛрд▓реНрдбрд░ рдХреЛ рдЙрд╕реА рдирд╛рдо рдХреЗ рд╕рд╛рде рдкреНрд▓рдЧ рдЗрди рдХреЗ рд░реВрдк рдореЗрдВ рдирд╛рдо рджреЗрдВред рдпрд╣ рд╡рд┐рдзрд┐ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рдШрдЯрдирд╛ рдХреЛ рдХрдо рдХрд░рддреА рд╣реИ!
рдЬрдм рдПрдХ рдкреНрд▓рдЧрдЗрди рдХреЛ рдХрд┐рд╕реА рджреГрд╢реНрдп рдореЗрдВ рдХреБрдЫ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдореЗрдВ рдорд╛рдирдХ Redmine рджреГрд╢реНрдп рдореЗрдВ рдХреБрдЫ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рдФрд░ рдЧрд▓рдд рддрд░реАрдХрд╛ рдкреНрд▓рдЧрдЗрди рдХреЗ рдЕрдВрджрд░ рдХреЗ рджреГрд╢реНрдп рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдирд╛ рд╣реИред рдЖрдорддреМрд░ рдкрд░ рдпрд╣ Redmine рдХрд░реНрдиреЗрд▓ рд╕реЗ рд╡реНрдпреВ рдлрд╛рдЗрд▓ рдХреЛ рдкреНрд▓рдЧрдЗрди рдХреА рдЙрдЪрд┐рдд рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдореЗрдВ рдХреЙрдкреА рдХрд░рдХреЗ рдФрд░ рдлрд┐рд░ рдЗрд╕ рдлрд╛рдЗрд▓ рдХреЛ рдПрдбрд┐рдЯ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдПрдХ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдореЗрдВ, рд╣рдо рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рд╣реЗрдЬрдиреЗ рд╡рд╛рд▓реЗ рдлреЙрд░реНрдо рдХреЗ рд╕рд╛рде рджреГрд╢реНрдп рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрддреЗ рд╣реИрдВред

рдХреНрдпреЛрдВ рдЗрддрдиреА рдмреБрд░реА рддрд░рд╣ рд╕реЗ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП:
- рдЕрдкрдиреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреА рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХрддрд╛ рдХреА рдирд┐рд░рдВрддрд░ рдирд┐рдЧрд░рд╛рдиреА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдк рдЦреБрдж рдХреЛ рдкреНрд░рдпрд╛рд╕рд░рдд рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдЗрд╕ рджреГрд╢реНрдп рдореЗрдВ Redmine рдХреЗ рдирдП рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдХреБрдЫ рдкрд░рд┐рд╡рд░реНрддрди рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЖрдк рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдЦреЛ рджреЗрдВрдЧреЗред рдПрдХ рджреГрд╢реНрдп рдХреА рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХрддрд╛ рдкрд░ рдирдЬрд╝рд░ рд░рдЦрдирд╛ рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рд╣реИред
- рдпрджрд┐ рдПрдХ рдФрд░ рдкреНрд▓рдЧрдЗрди рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ рдЬреЛ рд╕рдорд╛рди рджреГрд╢реНрдп рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрддрд╛ рд╣реИ, рддреЛ рдпрд╛ рддреЛ рдЖрдкрдХрд╛ рджреГрд╢реНрдп рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд▓рдЧрдЗрди рдХрд╛ рджреГрд╢реНрдп рд▓рд╛рдЧреВ рд╣реЛрдЧрд╛ред рдЖрд╡реЗрджрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреМрди рд╕рд╛ рджреГрд╢реНрдп рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХреЗ рдЖрджреЗрд╢ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рд╡реИрдХрд▓реНрдкрд┐рдХ рддрд░реАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред
hooky
рдПрдХ рджреГрд╢реНрдп рдореЗрдВ рдПрдХ рд╣реБрдХ рдХреЛрдб рдХреА рдПрдХ рдкрдВрдХреНрддрд┐ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдПрдХ рджреГрд╢реНрдп рдореЗрдВ рдЕрдкрдиреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдПрдореНрдмреЗрдб рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдПрдХ рд╣реБрдХ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдмрд╕ рд╕рднреА Redmine рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ "рд╣реБрдХ" рдХреА рдЦреЛрдЬ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдпрд╛ рдЖрдк
рдЗрд╕ рдкреНрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╣реБрдХ рд╣реБрдХ
рд╣рдо рд╕рднреА рджреГрд╢реНрдп рд╣реБрдХ рдХрдиреЗрдХреНрд╢рдиреЛрдВ рдХреЛ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдЗрд╕ рддрд░рд╣ init.rb рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:
require 'luxury_buttons/view_hooks'
рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рд╣реА рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛ рд╕рдХрддреА рд╣реИ:
module LuxuryButtons module LuxuryButtons class Hooks < Redmine::Hook::ViewListener render_on( :view_issues_form_details_top, :partial => 'lu_buttons/view_issues_form_details_top') render_on( :view_layouts_base_html_head, :partial => 'lu_buttons/page_header') render_on( :view_issues_show_description_bottom, :partial => "lu_buttons/button_bar" ) render_on( :view_issues_history_journal_bottom, :partial => "lu_buttons/journal_detail") end end end
рдкрд╣рд▓реЗ рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдирд╛рдо рдкреНрд▓рдЧрдЗрди рдХреЗ рдирд╛рдо рд╕реЗ рдореЗрд▓ рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рджреВрд╕рд░рд╛ -
рдкреИрдЪ рдлрд╝реЛрд▓реНрдбрд░ рдХреЗ рдирд╛рдо рдХреЗ рд╕рд╛рдеред
рдХреНрд▓рд╛рд╕ рдХреЗ рдЕрдВрджрд░ рдРрд╕реЗ рдлрдВрдХреНрд╢рдиреНрд╕ рд╣реЛрддреЗ рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рдпрд╣ рджрд┐рдЦрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕ рд╣реБрдХ рдХреЛ рд░реЗрдВрдбрд░ рдХрд░рдирд╛ рд╣реИред
рдпрджрд┐ рджреЛ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдПрдХ рд╣реА рд╣реБрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рддреЛ рдкрд╣рд▓реЗ рдФрд░ рджреВрд╕рд░реЗ рджреЛрдиреЛрдВ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХреА рд╕рд╛рдордЧреНрд░реА рджреГрд╢реНрдп рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдЧреАред рдпрд╛рдиреА рд╣реБрдХ рдПрдХ рджреВрд╕рд░реЗ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдирд╛ рдирд╣реАрдВ рд╣реИред
рд╣реБрдХ рдХреЗ рд╕рд╛рде рджреЛ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ:
- рдПрдХ рд╣реБрдХ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
- рдХрднреА-рдХрднреА рдЖрдкрдХреЛ рджреГрд╢реНрдп рд╕реЗ рдХреБрдЫ рд╣рдЯрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рд╣реБрдХ рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рд╣рдордиреЗ рдЗрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рдпрд╛ рд╣реИ рд╡рд╣ рдкреГрд╖реНрда рдкрд░ рд╕рд╛рдордЧреНрд░реА рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП jQuery рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ рдЬрдм рджреГрд╢реНрдп рдкрд╣рд▓реЗ рд╣реА рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдЗрд╕рдХреЗ рд▓рд┐рдП, рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ "view_layouts_base_html_head" рд╣реБрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рдпрд╣ рдЖрдкрдХреЛ рдкреЗрдЬ рд╣реЗрдбрд░ рдореЗрдВ рд╕рд╛рдордЧреНрд░реА рдбрд╛рд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╣рдореЗрдВ рдХреБрдЫ DOM рддрддреНрд╡реЛрдВ рдХреЛ рдХрд╛рдЯрдиреЗ рдпрд╛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рддрд░реНрдХ рдХреЗ рд╕рд╛рде js рдлрд╝рд╛рдЗрд▓ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рддрд╛рдХрд┐ рдпрд╣ js-file рдЙрди рдкреГрд╖реНрдареЛрдВ рдкрд░ рд▓реЛрдб рди рд╣реЛ, рдЬрд┐рди рдкрд░ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рдХреЗ рд▓реЛрдб рдХреЛ рд╕рд╢рд░реНрдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдореЗрдВ рд▓реЛрдб рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред рдпрд╛рдиреА рдПрдХреНрд╢рди рдФрд░ рдХрдВрдЯреНрд░реЛрд▓рд░ рджреНрд╡рд╛рд░рд╛ рдлрд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб рдХреЛ рдХрд╛рдЯ рджрд┐рдпрд╛ рдЧрдпрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:
<% if controller_name == 'issues' && action_name == 'update' %> <%= javascript_include_tag :luxury_buttons_common, :plugin => :luxury_buttons %> <% end %>
рдкреНрд▓рдЧрдЗрди рдХреА рд╕рдВрдкрддреНрддрд┐ / рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ "Luxury_buttons_common.js" рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП:
jQuery(document).ready(function(){
рдХрднреА-рдХрднреА, рдпрд╣ js рдлрд╝рд╛рдЗрд▓ рдХрдиреЗрдХреНрд╢рди рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ "view_layouts_base_html_head" рд╣реБрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдореНрдмреЗрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕рдХреНрд╖рдо рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реБрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬреЛ рд╕реАрдорд┐рдд рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдкреГрд╖реНрдареЛрдВ рдкрд░ рд╕рд╛рдордЧреНрд░реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рд╣рдореЗрдВ рдХрд╛рд░реНрдп рдкреГрд╖реНрда рдкрд░ рдХреБрдЫ рдЬреЛрдбрд╝рдирд╛ рдпрд╛ рдХрд╛рдЯрдирд╛ рд╣реИ, рддреЛ рд╣рдо "view_issues_form_details_bottom" рд╣реБрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рддрд╛рдХрд┐ рдлрд╝рд╛рдЗрд▓ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдирд┐рдХрд╛рдп рд╕реЗ рдХрдиреЗрдХреНрдЯ рди рд╣реЛ, рд▓реЗрдХрд┐рди рд╢реАрд░реНрд╖ рд▓реЗрдЦ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
<% content_for :header_tags do %> <%= javascript_include_tag :luxury_buttons_common, :plugin => :luxury_buttons %> <% end %>
рд╕рдЪ рд╣реИ, рдкреНрд▓рдЧрдЗрдиреНрд╕ рдореЗрдВ "content_for" рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде, рд╕рдВрд╕реНрдХрд░рдг рд╕реЗ рд╕рдВрд╕реНрдХрд░рдг рддрдХ
рдХрдард┐рдирд╛рдЗрдпрд╛рдВ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИрдВ ред
рдореЙрдбрд▓, рдирд┐рдпрдВрддреНрд░рдХ рдФрд░ рд╕рд╣рд╛рдпрдХреЛрдВ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рдХреИрд╕реЗ рдмрджрд▓реЗрдВред
рдмрджрд▓рддреЗ рд╣реБрдП (рдкреИрдЪрд┐рдВрдЧ) рддрд░реАрдХреЗ рдХрдИ рдорд╛рдпрдиреЛрдВ рдореЗрдВ рдмрджрд▓рддреЗ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЗ рд╕рдорд╛рди рд╣реИрдВ рдФрд░ рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛рдПрдВ рд▓рд╛рддреЗ рд╣реИрдВред
рдирд┐рдпрдВрддреНрд░рдХ рдФрд░ рдореЙрдбрд▓ рдореЗрдВ рд╣реБрдХ
рдирд┐рдпрдВрддреНрд░рдХ рдФрд░ рдореЙрдбрд▓ рдореЗрдВ рднреА рд╣реБрдХ рд╣реИрдВред рд╡реЗ рдЕрд▓рдЧ рддрд░рд╣ рд╕реЗ рдЬреБрдбрд╝рддреЗ рд╣реИрдВред Init.rb рдореЗрдВ рдПрдХ рд░реЗрдЦрд╛ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП рдЬреЛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реБрдХ рдХреЛ рдЬреЛрдбрд╝рддреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╣реБрдХ рдЬрд┐рд╕реЗ рдирдП рдХрд╛рд░реНрдп рдХреЛ рд╕рд╣реЗрдЬрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ:
require 'luxury_buttons/controller_issues_new_before_save_hook'
рдкреИрдЪ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ "рдХрдВрдЯреНрд░реЛрд▓рд░_рдЗрдВрд╕реВ_рдиреНрдпреВ_рдмреЗрдЕрд░_рд╕реИрд╡_рд╣реВрдХред рдЖрд░рдмреА" рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде:
module LuxuryButtons class ControllerIssuesNewBeforeSaveHook < Redmine::Hook::ViewListener def controller_issues_new_before_save(context={}) if context[:params] && context[:params][:issue] if (not context[:params][:issue][:assigned_to_id].nil?) and context[:params][:issue][:assigned_to_id].to_s=='' context[:issue].assigned_to_id = context[:issue].author_id if context[:issue].new_record? and Setting.plugin_luxury_buttons['assign_to_author'] end end '' end end end
рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдирд╛рдо рдкреНрд▓рдЧрдЗрди рдХреЗ рдирд╛рдо, рдлрд╝рд╛рдЗрд▓ рдХреЗ рдирд╛рдо рдХреЗ рд╕рд╛рде рд╡рд░реНрдЧ рдХреЗ рдирд╛рдо рд╕реЗ рдореЗрд▓ рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдореЗрдВ рд▓реЗрдЦрдХ рдХреЛ рдПрдХ рдирдпрд╛ рдХрд╛рд░реНрдп рд╕реМрдВрдкрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдХрд╛ рдПрд╣рд╕рд╛рд╕ рд╣реЛрддрд╛ рд╣реИред
рдкреИрдЪ рд╡рд┐рдзрд┐
рдЬреИрд╕рд╛ рдХрд┐ рд╡рд┐рдЪрд╛рд░реЛрдВ рдореЗрдВ, рд░реЗрдбрдорд╛рдЗрди рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╣реБрдХ рд╣рдореЗрд╢рд╛ рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВред рдФрд░ рдлрд┐рд░ рдЖрдкрдХреЛ рдореЙрдбрд▓, рд╕рд╣рд╛рдпрдХ рдпрд╛ рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рдкреИрдЪ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ init.rb рдореЗрдВ рдкреИрдЪ рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд╕рдорд╕реНрдпрд╛ рдореЙрдбрд▓ рдХреА read_only_attribute_names рд╡рд┐рдзрд┐ рдХреЛ рдкреИрдЪ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
Rails.application.config.to_prepare do Issue.send(:include, LuxuryButtons::IssuePatch) end
рдкреИрдЪ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ "issue_patch.rb" рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рд▓рдЧрднрдЧ рдирд┐рдореНрди рд╕рд╛рдордЧреНрд░реА:
module LuxuryButtons module IssuePatch def self.included(base) base.extend(ClassMethods) base.send(:include, InstanceMethods) base.class_eval do alias_method_chain :read_only_attribute_names, :luxury_buttons end end module ClassMethods end module InstanceMethods def read_only_attribute_names_with_luxury_buttons(user) attribute = read_only_attribute_names_without_luxury_buttons(user) if Setting.plugin_luxury_buttons['hidden_fields_into_new_issue_form'] && new_record? hidden_fields = Setting.plugin_luxury_buttons['hidden_fields_into_new_issue_form'] attribute += hidden_fields attribute end attribute end end end end
рдбрд┐рдЬрд╝рд╛рдЗрди
alias_method_chain :read_only_attribute_names, :luxury_buttons
рд╣рдо рджреЛ read_only_attribute_names_with_l рдЧрдгрд┐рдд_buttons рдкрдврд╝рддреЗ рд╣реИрдВ рдФрд░ read_only_attribute_names_without_l рдЧрдгрд┐рдд_buttons рд╡рд┐рдзрд┐рдпрд╛рдБ рдкрдврд╝рддреЗ рд╣реИрдВред
рдкрд╣рд▓рд╛ рддрд░реАрдХрд╛ рдЕрдм рдорд╛рдирдХ read_only_attribute_names рдореЙрдбрд▓ рд╡рд┐рдзрд┐ рдХреЗ рдмрдЬрд╛рдп рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛, рджреВрд╕рд░рд╛ рддрд░реАрдХрд╛ standard read_only_attribute_names рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдирд╛рдо рд╣реИред
рджреЛ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдорд┐рд▓рд╛рдХрд░, рдЖрдк рдорд╛рдирдХ Redmine рд╡рд┐рдзрд┐ рдХреЛ рдкреИрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдо рдкрд╣рд▓реЗ рдорд╛рдирдХ Redmine рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВ, рдЬреЛ рдорд╛рдиреЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░, рдЗрд╕ рд╕рд░рдгреА рдореЗрдВ рдорд╛рди рдЬреЛрдбрд╝реЗрдВред
рдпрджрд┐ рдирдП рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдорд╛рдирдХ Redmine рд╡рд┐рдзрд┐ рдореЗрдВ рдХреБрдЫ рдкрд░рд┐рд╡рд░реНрддрди рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рд╣рдорд╛рд░рд╛ рдкреИрдЪ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рдЕрдЧрд░ рд╣рдо рдмрд╕ рдорд╛рдирдХ Redmine рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рдореЗрдВ рдЕрдкрдирд╛ рддрд░реНрдХ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИред
рдорд╣рддреНрд╡рдкреВрд░реНрдг! Redmine
рдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореЙрдбрд▓ рдХреЛ рдкреИрдЪ рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рдХреБрдЫ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВред рд╕рд╣реА рдкреИрдЪрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╢рд╛рдорд┐рд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:
require_dependency 'project' require_dependency 'principal' require_dependency 'user'
рд▓реЗрдЦ рдореЗрдВ рд╡рд╣ рд╕рдм рдХреБрдЫ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдореИрдВ Redmine рдХреЗ рд▓рд┐рдП рдкреНрд▓рдЧрдЗрдиреНрд╕ рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХрд╣рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред рдореИрдВрдиреЗ рдореВрд▓ рдкрджреНрдзрддрд┐рдпреЛрдВ рдФрд░ рдиреБрдХрд╕рд╛рди рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреАред рдЖрд╢рд╛ рд╣реИ рдХрд┐ рд▓реЗрдЦ рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред