radiant-database_mailer-extension 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/README.md +159 -0
  2. data/Rakefile +120 -0
  3. data/app/controllers/admin/form_datas_controller.rb +77 -0
  4. data/app/controllers/database_mailer_processing.rb +19 -0
  5. data/app/helpers/admin/form_datas_helper.rb +57 -0
  6. data/app/models/form_data.rb +93 -0
  7. data/app/models/form_data_asset.rb +14 -0
  8. data/app/views/admin/form_datas/_export.html.haml +33 -0
  9. data/app/views/admin/form_datas/_filters.html.haml +27 -0
  10. data/app/views/admin/form_datas/index.html.haml +34 -0
  11. data/app/views/admin/form_datas/show.html.haml +49 -0
  12. data/config/routes.rb +7 -0
  13. data/database_mailer_extension.rb +31 -0
  14. data/db/migrate/001_create_form_datas.rb +16 -0
  15. data/db/migrate/002_add_data_columns.rb +13 -0
  16. data/db/migrate/20090722135916_create_form_data_assets.rb +21 -0
  17. data/features/datasets/database_mailer_dataset.rb +19 -0
  18. data/features/datasets/mailers_dataset.rb +69 -0
  19. data/features/fixtures/attachment.jpg +0 -0
  20. data/features/saving_emails_to_database.feature +45 -0
  21. data/features/step_definitions/admin_steps.rb +6 -0
  22. data/features/step_definitions/email_steps.rb +73 -0
  23. data/features/step_definitions/form_data_steps.rb +3 -0
  24. data/features/step_definitions/webrat_steps.rb +119 -0
  25. data/features/support/env.rb +28 -0
  26. data/features/support/paths.rb +25 -0
  27. data/lib/radiant-database_mailer-extension.rb +8 -0
  28. data/lib/tasks/database_mailer_extension_tasks.rake +31 -0
  29. data/public/javascripts/admin/database_mailer.js +73 -0
  30. data/public/stylesheets/sass/admin/database_mailer.sass +235 -0
  31. data/radiant-database_mailer-extension.gemspec +26 -0
  32. data/spec/controllers/form_datas_controller_spec.rb +272 -0
  33. data/spec/controllers/mail_controller_spec.rb +40 -0
  34. data/spec/helpers/form_datas_helper_spec.rb +5 -0
  35. data/spec/models/form_data_asset_spec.rb +11 -0
  36. data/spec/models/form_data_spec.rb +151 -0
  37. data/spec/spec.opts +6 -0
  38. data/spec/spec_helper.rb +37 -0
  39. data/spec/views/index.html.erb_spec.rb +25 -0
  40. metadata +139 -0
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.namespace :admin do |admin|
3
+ admin.resources :form_datas do |form_data|
4
+ form_data.resources :form_data_assets
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,31 @@
1
+ require_dependency 'application_controller'
2
+ require 'radiant-database_mailer-extension/version'
3
+
4
+ class DatabaseMailerExtension < Radiant::Extension
5
+ version RadiantDatabaseMailerExtension::VERSION
6
+ description RadiantDatabaseMailerExtension::DESCRIPTION
7
+ url RadiantDatabaseMailerExtension::URL
8
+
9
+ def activate
10
+ throw "MailerExtension must be loaded before DatabaseMailerExtension" unless defined?(MailerExtension)
11
+ MailController.class_eval do
12
+ include DatabaseMailerProcessing
13
+ alias_method_chain :process_mail, :database
14
+ end
15
+
16
+ MailerProcess.class_eval do
17
+ include DatabaseMailerProcessing
18
+ alias_method_chain :process_mail, :database
19
+ end
20
+ admin.tabs.add "Database Mailer", "/admin/form_datas", :after => "Layouts", :visibility => [:all]
21
+
22
+ tab "Content" do
23
+ add_item "Database Mailer", "/admin/form_datas"
24
+ end
25
+
26
+ Mime::Type.register "application/vnd.ms-excel", :xls
27
+ end
28
+
29
+ def deactivate
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ class CreateFormDatas < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :form_datas do |t|
4
+ t.column :url, :string
5
+ t.column :blob, :text
6
+ t.column :exported, :datetime
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :form_datas, :url
11
+ end
12
+
13
+ def self.down
14
+ drop_table :form_datas
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ class AddDataColumns < ActiveRecord::Migration
2
+ def self.up
3
+ DATABASE_MAILER_COLUMNS.each do |k, v|
4
+ unless FormData.column_names.include?(k.to_s)
5
+ add_column(:form_datas, k, v)
6
+ add_index(:form_datas, k) unless v == :text
7
+ end
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ class CreateFormDataAssets < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :form_data_assets do |t|
4
+ t.references :form_data
5
+ t.string :field_name
6
+ t.string :attachment_file_name
7
+ t.string :attachment_content_type
8
+ t.integer :attachment_file_size
9
+ t.datetime :attachment_updated_at
10
+
11
+ t.timestamps
12
+ end
13
+
14
+ add_index :form_data_assets, :form_data_id
15
+ end
16
+
17
+ def self.down
18
+ remove_index :form_data_assets, :form_data_id
19
+ drop_table :form_data_assets
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ class DatabaseMailerDataset < Dataset::Base
2
+
3
+ def load
4
+ create_record :form_datas, :eric_cartman, {
5
+ :name => "Eric Cartman",
6
+ :email => "eric_cartman@example.com",
7
+ :message => "test message"
8
+ }
9
+
10
+ create_record :form_data_assets, :attachment, {
11
+ :form_data_id => form_datas(:eric_cartman).id,
12
+ :field_name => "attachment",
13
+ :attachment_file_name => "attachment.jpg",
14
+ :attachment_content_type => "image/jpg",
15
+ :attachment_file_size => "1234"
16
+ }
17
+ end
18
+
19
+ end
@@ -0,0 +1,69 @@
1
+ class MailersDataset < Dataset::Base
2
+ uses :home_page
3
+
4
+ def load
5
+ create_page "Contact" do
6
+ create_page_part "contact_body",
7
+ :name => "body",
8
+ :content => %Q{
9
+ <r:mailer:form>
10
+ <label for="name">Name:</label><br/>
11
+ <r:mailer:text name="name" /><br/>
12
+
13
+ <label for="email">Email:</label><br/>
14
+ <r:mailer:text name="email" /><br/>
15
+
16
+ <label for="message">Message:</label><br/>
17
+ <r:mailer:textarea name="message" /> <br/>
18
+
19
+ <label for="attachment">Image:</label><br/>
20
+ <r:mailer:file name="attachment" /><br/>
21
+
22
+ <input type="submit" value="Send" />
23
+ </r:mailer:form>}
24
+
25
+ create_page_part "contact_mailer",
26
+ :name => "mailer",
27
+ :content => %Q{
28
+ subject: Contact email
29
+ from: website@example.com
30
+ redirect_to: /contact/thank-you
31
+ recipients:
32
+ - contact@example.com
33
+ }
34
+ create_page "Thank you"
35
+ end
36
+
37
+ create_page "Contact No Save" do
38
+ create_page_part "contact_body_no_save",
39
+ :name => "body",
40
+ :content => %Q{
41
+ <r:mailer:form>
42
+ <label for="name">Name:</label><br/>
43
+ <r:mailer:text name="name" /><br/>
44
+
45
+ <label for="email">Email:</label><br/>
46
+ <r:mailer:text name="email" /><br/>
47
+
48
+ <label for="message">Message:</label><br/>
49
+ <r:mailer:textarea name="message" /> <br/>
50
+
51
+ <label for="attachment">Image:</label><br/>
52
+ <r:mailer:file name="attachment" /><br/>
53
+
54
+ <input type="submit" value="Send" />
55
+ </r:mailer:form>}
56
+
57
+ create_page_part "mailer_no_save",
58
+ :name => 'mailer',
59
+ :content => %Q{
60
+ subject: Contact email
61
+ from: website@example.com
62
+ redirect_to: /contact/thank-you
63
+ save_to_database: false
64
+ recipients:
65
+ - contact@example.com
66
+ }
67
+ end
68
+ end
69
+ end
Binary file
@@ -0,0 +1,45 @@
1
+ Feature: Database Mailer
2
+ In order to add database persistency to emailed forms
3
+ As an admin
4
+ I want to manage form fields
5
+
6
+ Background:
7
+ Given I am logged in as an admin
8
+
9
+ Scenario: Saving an email to database if 'save_to_database' is true
10
+ Given I am on the contact page
11
+ And I fill in "Name" with "Stan Marsh"
12
+ And I fill in "Email" with "stan_marsh@example.com"
13
+ And I fill in "Message" with "Hello from South Park"
14
+ And I fill in "attachment"
15
+ When I press "Send"
16
+ # email is sent
17
+ Then I should be on the thank you page
18
+ And "contact@example.com" should receive 1 email
19
+ # email is saved to database
20
+ When I go to the form datas index
21
+ Then I should see "Stan Marsh"
22
+ And I should see "Hello from South Park"
23
+ # email attachment is saved to database
24
+ When I follow "Show"
25
+ Then I should see "attachment.jpg"
26
+
27
+ Scenario: Sending an email without saving it to the database
28
+ Given I am on the contact no save page
29
+ And I fill in "Name" with "Stan Marsh"
30
+ And I fill in "Email" with "stan_marsh@example.com"
31
+ And I fill in "Message" with "Hello from South Park"
32
+ And I fill in "attachment"
33
+ When I press "Send"
34
+ Then I should be on the thank you page
35
+ And "contact@example.com" should receive 1 email
36
+ When I go to the form datas index
37
+ Then I should not see "Stan Marsh"
38
+ And I should not see "Hello from South Park"
39
+
40
+ Scenario: Deleting an existing form data
41
+ Given I am on the form datas index
42
+ When I follow "Delete"
43
+ Then I should be on the form datas index
44
+ And I should see "Record deleted!"
45
+ And I should not see "Eric Cartman"
@@ -0,0 +1,6 @@
1
+ Given /^I am logged in as an admin$/ do
2
+ Given "I go to to \"the welcome page\""
3
+ When "I fill in \"Username\" with \"admin\""
4
+ When "I fill in \"Password\" with \"password\""
5
+ When "I press \"Login\""
6
+ end
@@ -0,0 +1,73 @@
1
+ #Commonly used email steps
2
+ #
3
+ # To add your own steps make a custom_email_steps.rb
4
+ # The provided methods are:
5
+ #
6
+ # reset_mailer
7
+ # open_last_email
8
+ # visit_in_email
9
+ # unread_emails_for
10
+ # mailbox_for
11
+ # current_email
12
+ # open_email
13
+ # read_emails_for
14
+ # find_email
15
+
16
+ module EmailHelpers
17
+ def current_email_address
18
+ "example@aissac.ro" # Replace with your a way to find your current_email. e.g current_user.email
19
+ end
20
+ end
21
+ World(EmailHelpers)
22
+
23
+ # Use this step to reset the e-mail queue within a scenario.
24
+ # This is done automatically before each scenario.
25
+ Given /^(?:a clear email queue|no emails have been sent)$/ do
26
+ reset_mailer
27
+ end
28
+
29
+ # Use this step to open the most recently sent e-mail.
30
+ When /^I open the email$/ do
31
+ open_email(current_email_address)
32
+ end
33
+
34
+ When %r{^I follow "([^"]*?)" in the email$} do |link|
35
+ visit_in_email(link)
36
+ end
37
+
38
+ Then /^I should receive (an|\d+) emails?$/ do |amount|
39
+ amount = 1 if amount == "an"
40
+ unread_emails_for(current_email_address).size.should == amount.to_i
41
+ end
42
+
43
+ Then %r{^"([^"]*?)" should receive (\d+) emails?$} do |address, n|
44
+ unread_emails_for(address).size.should == n.to_i
45
+ end
46
+
47
+ Then %r{^"([^"]*?)" should have (\d+) emails?$} do |address, n|
48
+ mailbox_for(address).size.should == n.to_i
49
+ end
50
+
51
+ Then %r{^"([^"]*?)" should not receive an email$} do |address|
52
+ find_email(address).should be_nil
53
+ end
54
+
55
+ Then %r{^I should see "([^"]*?)" in the subject$} do |text|
56
+ current_email.should have_subject(Regexp.new(text))
57
+ end
58
+
59
+ Then %r{^I should see "([^"]*?)" in the email$} do |text|
60
+ current_email.body.should =~ Regexp.new(text)
61
+ end
62
+
63
+ When %r{^"([^"]*?)" opens? the email with subject "([^"]*?)"$} do |address, subject|
64
+ open_email(address, :with_subject => subject)
65
+ end
66
+
67
+ When %r{^"([^"]*?)" opens? the email with text "([^"]*?)"$} do |address, text|
68
+ open_email(address, :with_text => text)
69
+ end
70
+
71
+ When /^I click the first link in the email$/ do
72
+ click_first_link_in_email
73
+ end
@@ -0,0 +1,3 @@
1
+ Given /^I fill in "([^\"]*)"$/ do |field|
2
+ fill_in(field, :with => "#{RAILS_ROOT}/vendor/extensions/database_mailer/features/fixtures/attachment.jpg")
3
+ end
@@ -0,0 +1,119 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths"))
2
+
3
+ # Commonly used webrat steps
4
+ # http://github.com/brynary/webrat
5
+
6
+ Given /^I am on (.+)$/ do |page_name|
7
+ visit path_to(page_name)
8
+ end
9
+
10
+ When /^I go to (.+)$/ do |page_name|
11
+ visit path_to(page_name)
12
+ end
13
+
14
+ When /^I press "([^\"]*)"$/ do |button|
15
+ click_button(button)
16
+ end
17
+
18
+ When /^I follow "([^\"]*)"$/ do |link|
19
+ click_link(link)
20
+ end
21
+
22
+ When /^I fill in "([^\"]*)" with "([^\"]*)"$/ do |field, value|
23
+ fill_in(field, :with => value)
24
+ end
25
+
26
+ When /^I select "([^\"]*)" from "([^\"]*)"$/ do |value, field|
27
+ select(value, :from => field)
28
+ end
29
+
30
+ # Use this step in conjunction with Rail's datetime_select helper. For example:
31
+ # When I select "December 25, 2008 10:00" as the date and time
32
+ When /^I select "([^\"]*)" as the date and time$/ do |time|
33
+ select_datetime(time)
34
+ end
35
+
36
+ # Use this step when using multiple datetime_select helpers on a page or
37
+ # you want to specify which datetime to select. Given the following view:
38
+ # <%= f.label :preferred %><br />
39
+ # <%= f.datetime_select :preferred %>
40
+ # <%= f.label :alternative %><br />
41
+ # <%= f.datetime_select :alternative %>
42
+ # The following steps would fill out the form:
43
+ # When I select "November 23, 2004 11:20" as the "Preferred" date and time
44
+ # And I select "November 25, 2004 10:30" as the "Alternative" date and time
45
+ When /^I select "([^\"]*)" as the "([^\"]*)" date and time$/ do |datetime, datetime_label|
46
+ select_datetime(datetime, :from => datetime_label)
47
+ end
48
+
49
+ # Use this step in conjunction with Rail's time_select helper. For example:
50
+ # When I select "2:20PM" as the time
51
+ # Note: Rail's default time helper provides 24-hour time-- not 12 hour time. Webrat
52
+ # will convert the 2:20PM to 14:20 and then select it.
53
+ When /^I select "([^\"]*)" as the time$/ do |time|
54
+ select_time(time)
55
+ end
56
+
57
+ # Use this step when using multiple time_select helpers on a page or you want to
58
+ # specify the name of the time on the form. For example:
59
+ # When I select "7:30AM" as the "Gym" time
60
+ When /^I select "([^\"]*)" as the "([^\"]*)" time$/ do |time, time_label|
61
+ select_time(time, :from => time_label)
62
+ end
63
+
64
+ # Use this step in conjunction with Rail's date_select helper. For example:
65
+ # When I select "February 20, 1981" as the date
66
+ When /^I select "([^\"]*)" as the date$/ do |date|
67
+ select_date(date)
68
+ end
69
+
70
+ # Use this step when using multiple date_select helpers on one page or
71
+ # you want to specify the name of the date on the form. For example:
72
+ # When I select "April 26, 1982" as the "Date of Birth" date
73
+ When /^I select "([^\"]*)" as the "([^\"]*)" date$/ do |date, date_label|
74
+ select_date(date, :from => date_label)
75
+ end
76
+
77
+ When /^I check "([^\"]*)"$/ do |field|
78
+ check(field)
79
+ end
80
+
81
+ When /^I uncheck "([^\"]*)"$/ do |field|
82
+ uncheck(field)
83
+ end
84
+
85
+ When /^I choose "([^\"]*)"$/ do |field|
86
+ choose(field)
87
+ end
88
+
89
+ When /^I attach the file at "([^\"]*)" to "([^\"]*)"$/ do |path, field|
90
+ attach_file(field, path)
91
+ end
92
+
93
+ Then /^I should see "([^\"]*)"$/ do |text|
94
+ response.should contain(text)
95
+ end
96
+
97
+ Then /^I should not see "([^\"]*)"$/ do |text|
98
+ response.should_not contain(text)
99
+ end
100
+
101
+ Then /^the "([^\"]*)" field should contain "([^\"]*)"$/ do |field, value|
102
+ field_labeled(field).value.should =~ /#{value}/
103
+ end
104
+
105
+ Then /^the "([^\"]*)" field should not contain "([^\"]*)"$/ do |field, value|
106
+ field_labeled(field).value.should_not =~ /#{value}/
107
+ end
108
+
109
+ Then /^the "([^\"]*)" checkbox should be checked$/ do |label|
110
+ field_labeled(label).should be_checked
111
+ end
112
+
113
+ Then /^the "([^\"]*)" checkbox should not be checked$/ do |label|
114
+ field_labeled(label).should_not be_checked
115
+ end
116
+
117
+ Then /^I should be on (.+)$/ do |page_name|
118
+ URI.parse(current_url).path.should == path_to(page_name)
119
+ end
@@ -0,0 +1,28 @@
1
+ # Sets up the Rails environment for Cucumber
2
+ ENV["RAILS_ENV"] = "test"
3
+ require File.expand_path(File.dirname(__FILE__) + '/../../../../../config/environment')
4
+
5
+ require 'cucumber/rails/world'
6
+ require 'cucumber/formatter/unicode' # Comment out this line if you don't want Cucumber Unicode support
7
+
8
+ require 'webrat'
9
+
10
+ Webrat.configure do |config|
11
+ config.mode = :rails
12
+ end
13
+
14
+ require 'spec'
15
+ require 'email_spec/cucumber'
16
+
17
+ # Comment out the next two lines if you're not using RSpec's matchers (should / should_not) in your steps.
18
+ require 'cucumber/rails/rspec'
19
+ require 'webrat/core/matchers'
20
+
21
+ Cucumber::Rails::World.class_eval do
22
+ include Dataset
23
+ datasets_directory "#{RADIANT_ROOT}/spec/datasets"
24
+ Dataset::Resolver.default = Dataset::DirectoryResolver.new("#{RADIANT_ROOT}/spec/datasets", File.dirname(__FILE__) + '/../datasets')
25
+ self.datasets_database_dump_path = "#{Rails.root}/tmp/dataset"
26
+
27
+ dataset :pages, :users, :mailers, :database_mailer
28
+ end
@@ -0,0 +1,25 @@
1
+ module NavigationHelpers
2
+ def path_to(page_name)
3
+ case page_name
4
+
5
+ when /the welcome page/
6
+ admin_path
7
+ when /the contact page/
8
+ '/contact'
9
+ when /the contact no save page/
10
+ '/contact-no-save'
11
+ when /the thank you page/
12
+ '/contact/thank-you'
13
+ when /the form datas index/
14
+ admin_form_datas_path
15
+
16
+ # Add more page name => path mappings here
17
+
18
+ else
19
+ raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
20
+ "Now, go and add a mapping in features/support/paths.rb"
21
+ end
22
+ end
23
+ end
24
+
25
+ World(NavigationHelpers)
@@ -0,0 +1,8 @@
1
+ module RadiantDatabaseMailerExtension
2
+ VERSION = '1.0.1'
3
+ SUMMARY = %q{Database mailer for Radiant CMS}
4
+ DESCRIPTION = %q{Save fields from mailer forms to the database.}
5
+ URL = "http://blog.aissac.ro/radiant/database-mailer-extension/"
6
+ AUTHORS = ["Cristi Duma", "Istvan Hoka"]
7
+ EMAIL = ["cristi.duma@aissac.ro"]
8
+ end
@@ -0,0 +1,31 @@
1
+ namespace :radiant do
2
+ namespace :extensions do
3
+ namespace :database_mailer do
4
+
5
+ desc "Runs the migration of the Database Mailer extension"
6
+ task :migrate => :environment do
7
+ require 'radiant/extension_migrator'
8
+
9
+ DatabaseMailerExtension.migrator.set_schema_version(1) if DatabaseMailerExtension.migrator.current_version > 1
10
+
11
+ if ENV["VERSION"]
12
+ DatabaseMailerExtension.migrator.migrate(ENV["VERSION"].to_i)
13
+ else
14
+ DatabaseMailerExtension.migrator.migrate
15
+ end
16
+ end
17
+
18
+ desc "Copies public assets of the Database Mailer to the instance public/ directory."
19
+ task :update => :environment do
20
+ is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
21
+ puts "Copying assets from DatabaseMailerExtension"
22
+ Dir[DatabaseMailerExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
23
+ path = file.sub(DatabaseMailerExtension.root, '')
24
+ directory = File.dirname(path)
25
+ mkdir_p RAILS_ROOT + directory, :verbose => false
26
+ cp file, RAILS_ROOT + path, :verbose => false
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,73 @@
1
+ document.observe("dom:loaded", function () {
2
+ var element = $('expander');
3
+ element.observe('click', function() {
4
+ if (element.up('#filters').hasClassName('expanded')) {
5
+ hideForm()
6
+ } else {
7
+ showForm()
8
+ }
9
+ });
10
+ center('blob-popup');
11
+ });
12
+
13
+ function hideForm() {
14
+ Effect.SlideUp('form',{ duration: 0.5, afterFinish:function() {
15
+ $('expander').up('#filters').removeClassName('expanded')
16
+ }
17
+ });
18
+ }
19
+
20
+ function showForm () {
21
+ $('expander').up('#filters').addClassName('expanded')
22
+ Effect.SlideDown('form', { duration: 0.5 });
23
+ }
24
+
25
+ function close() {
26
+ if ($('expander').up('#filters').hasClassName('expanded')) {
27
+ hideForm()
28
+ }
29
+ }
30
+
31
+
32
+ document.observe("dom:loaded", function () {
33
+ var element = $('x_expander');
34
+ element.observe('click', function() {
35
+ if (element.up('#x_filters').hasClassName('expanded')) {
36
+ hideXForm()
37
+ } else {
38
+ showXForm()
39
+ }
40
+ });
41
+ });
42
+
43
+ function hideXForm() {
44
+ Effect.SlideUp('x_form',{ duration: 0.5, afterFinish:function() {
45
+ $('x_expander').up('#x_filters').removeClassName('expanded')
46
+ }
47
+ });
48
+ }
49
+
50
+ function showXForm () {
51
+ $('x_expander').up('#x_filters').addClassName('expanded')
52
+ Effect.SlideDown('x_form', { duration: 0.5 });
53
+ }
54
+
55
+ function closeX() {
56
+ if ($('x_expander').up('#x_filters').hasClassName('expanded')) {
57
+ hideXForm()
58
+ }
59
+ }
60
+
61
+ function show_details() {
62
+ $('attachments').hide();
63
+ $('details').show();
64
+ $('details_lnk').addClassName('here');
65
+ $('attachments_lnk').removeClassName('here');
66
+ }
67
+
68
+ function show_attachments() {
69
+ $('attachments').show();
70
+ $('details').hide();
71
+ $('details_lnk').removeClassName('here');
72
+ $('attachments_lnk').addClassName('here');
73
+ }