effective_cpd 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +117 -0
  4. data/Rakefile +18 -0
  5. data/app/assets/config/effective_cpd_manifest.js +2 -0
  6. data/app/assets/javascripts/effective_cpd.js +2 -0
  7. data/app/assets/javascripts/effective_cpd/activities.js +49 -0
  8. data/app/assets/javascripts/effective_cpd/activities_new.js +21 -0
  9. data/app/assets/stylesheets/effective_cpd.scss +1 -0
  10. data/app/assets/stylesheets/effective_cpd/_activities.scss +19 -0
  11. data/app/controllers/admin/cpd_activities_controller.rb +13 -0
  12. data/app/controllers/admin/cpd_categories_controller.rb +13 -0
  13. data/app/controllers/admin/cpd_cycles_controller.rb +13 -0
  14. data/app/controllers/admin/cpd_rules_controller.rb +13 -0
  15. data/app/controllers/admin/cpd_statements_controller.rb +13 -0
  16. data/app/controllers/effective/cpd_cycles_controller.rb +19 -0
  17. data/app/controllers/effective/cpd_statement_activities_controller.rb +27 -0
  18. data/app/controllers/effective/cpd_statements_controller.rb +71 -0
  19. data/app/datatables/admin/effective_cpd_activities_datatable.rb +31 -0
  20. data/app/datatables/admin/effective_cpd_categories_datatable.rb +24 -0
  21. data/app/datatables/admin/effective_cpd_cycles_datatable.rb +22 -0
  22. data/app/datatables/admin/effective_cpd_rules_datatable.rb +43 -0
  23. data/app/datatables/admin/effective_cpd_statements_datatable.rb +30 -0
  24. data/app/datatables/effective_cpd_datatable.rb +30 -0
  25. data/app/datatables/effective_cpd_statements_datatable.rb +23 -0
  26. data/app/helpers/effective_cpd_helper.rb +37 -0
  27. data/app/mailers/effective/cpd_mailer.rb +7 -0
  28. data/app/models/effective/cpd_activity.rb +41 -0
  29. data/app/models/effective/cpd_category.rb +35 -0
  30. data/app/models/effective/cpd_cycle.rb +113 -0
  31. data/app/models/effective/cpd_rule.rb +108 -0
  32. data/app/models/effective/cpd_scorer.rb +158 -0
  33. data/app/models/effective/cpd_statement.rb +95 -0
  34. data/app/models/effective/cpd_statement_activity.rb +78 -0
  35. data/app/views/admin/cpd_activities/_form.html.haml +20 -0
  36. data/app/views/admin/cpd_categories/_form.html.haml +21 -0
  37. data/app/views/admin/cpd_categories/_form_cpd_category.html.haml +5 -0
  38. data/app/views/admin/cpd_cycles/_form.html.haml +17 -0
  39. data/app/views/admin/cpd_cycles/_form_content.html.haml +32 -0
  40. data/app/views/admin/cpd_cycles/_form_cpd_cycle.html.haml +21 -0
  41. data/app/views/admin/cpd_cycles/_form_cpd_rules.html.haml +56 -0
  42. data/app/views/admin/cpd_statements/_form.html.haml +6 -0
  43. data/app/views/effective/cpd_statement_activities/_form.html.haml +70 -0
  44. data/app/views/effective/cpd_statements/_activities.html.haml +64 -0
  45. data/app/views/effective/cpd_statements/_activities_new.html.haml +39 -0
  46. data/app/views/effective/cpd_statements/_agreements.html.haml +6 -0
  47. data/app/views/effective/cpd_statements/_cpd_statement.html.haml +5 -0
  48. data/app/views/effective/cpd_statements/_layout.html.haml +37 -0
  49. data/app/views/effective/cpd_statements/_summary.html.haml +36 -0
  50. data/app/views/effective/cpd_statements/activities.html.haml +25 -0
  51. data/app/views/effective/cpd_statements/agreements.html.haml +14 -0
  52. data/app/views/effective/cpd_statements/complete.html.haml +13 -0
  53. data/app/views/effective/cpd_statements/start.html.haml +13 -0
  54. data/app/views/effective/cpd_statements/submit.html.haml +20 -0
  55. data/app/views/layouts/effective_cpd_mailer_layout.html.haml +7 -0
  56. data/config/effective_cpd.rb +29 -0
  57. data/config/routes.rb +28 -0
  58. data/db/migrate/01_create_effective_cpd.rb.erb +98 -0
  59. data/db/seeds.rb +472 -0
  60. data/lib/effective_cpd.rb +18 -0
  61. data/lib/effective_cpd/engine.rb +11 -0
  62. data/lib/effective_cpd/version.rb +3 -0
  63. data/lib/generators/effective_cpd/install_generator.rb +46 -0
  64. data/lib/generators/templates/effective_cpd_mailer_preview.rb +4 -0
  65. data/lib/tasks/effective_cpd_tasks.rake +6 -0
  66. metadata +233 -0
@@ -0,0 +1,21 @@
1
+ = tabs do
2
+ = tab 'Category' do
3
+ - if cpd_category.persisted?
4
+ .alert.alert-warning
5
+ Changes to categories and activities will be displayed in all #{cpd_cycles_label}.
6
+
7
+ = render 'admin/cpd_categories/form_cpd_category', cpd_category: cpd_category
8
+
9
+ - if cpd_category.persisted?
10
+ %h2 Activities
11
+ %p
12
+ After adding an activity here, please visit any existing
13
+ = link_to(cpd_cycles_label.titleize + ' Settings', effective_cpd.admin_cpd_cycles_path)
14
+ pages and build a rule before it will be displayed.
15
+
16
+ - datatable = Admin::EffectiveCpdActivitiesDatatable.new(cpd_category_id: cpd_category.id)
17
+ = render_datatable(datatable, inline: true, simple: true)
18
+
19
+ - if cpd_category.persisted? && cpd_category.respond_to?(:log_changes_datatable)
20
+ = tab 'Logs' do
21
+ = render_datatable(cpd_category.log_changes_datatable)
@@ -0,0 +1,5 @@
1
+ = effective_form_with(model: [:admin, cpd_category], engine: true) do |f|
2
+ = f.text_field :title
3
+ = f.rich_text_area :body
4
+
5
+ = effective_submit(f)
@@ -0,0 +1,17 @@
1
+ = tabs do
2
+ = tab 'Cycle' do
3
+ = render 'admin/cpd_cycles/form_cpd_cycle', cpd_cycle: cpd_cycle
4
+
5
+ - if cpd_cycle.persisted?
6
+ = tab 'Content' do
7
+ = render 'admin/cpd_cycles/form_content', cpd_cycle: cpd_cycle
8
+
9
+ = tab 'Category and Activity Rules' do
10
+ = tabs do
11
+ - Effective::CpdCategory.deep.sorted.each do |cpd_category|
12
+ = tab(cpd_category.to_s) do
13
+ = render 'admin/cpd_cycles/form_cpd_rules', cpd_cycle: cpd_cycle, cpd_category: cpd_category
14
+
15
+ - if cpd_cycle.respond_to?(:log_changes_datatable)
16
+ = tab 'Logs' do
17
+ = render_datatable(cpd_cycle.log_changes_datatable)
@@ -0,0 +1,32 @@
1
+ = effective_form_with(model: [:admin, cpd_cycle], engine: true) do |f|
2
+ .card.mb-4
3
+ .card-body
4
+ %h5.card-title All Steps Content
5
+ = f.rich_text_area :all_steps_content, label: false, hint: 'displayed on all statement steps'
6
+
7
+ .card.mb-4
8
+ .card-body
9
+ %h5.card-title Start Step
10
+ = f.rich_text_area :start_content, label: false, hint: 'displayed on the start step only'
11
+
12
+ .card.mb-4
13
+ .card-body
14
+ %h5.card-title Activities Step
15
+ = f.rich_text_area :activities_content, label: false, hint: 'displayed on the activities step only'
16
+
17
+ .card.mb-4
18
+ .card-body
19
+ %h5.card-title Agreements Step
20
+ = f.rich_text_area :agreements_content, label: false, hint: 'displayed on the agreements step only'
21
+
22
+ .card.mb-4
23
+ .card-body
24
+ %h5.card-title Submit Step
25
+ = f.rich_text_area :submit_content, label: false, hint: 'displayed on the submit step only'
26
+
27
+ .card.mb-4
28
+ .card-body
29
+ %h5.card-title Complete Step
30
+ = f.rich_text_area :complete_content, label: false, hint: 'displayed on the complete step only'
31
+
32
+ = f.submit
@@ -0,0 +1,21 @@
1
+ = effective_form_with(model: [:admin, cpd_cycle], engine: true) do |f|
2
+ = f.text_field :title,
3
+ hint: "The title of this #{cpd_cycle_label}. Something like #{Time.zone.now.year} Continuing Professional Development"
4
+
5
+ = f.date_field :start_at,
6
+ hint: "The first date statements may be submited for this #{cpd_cycle_label}"
7
+
8
+ = f.date_field :end_at,
9
+ hint: "The last date statements may be created for this #{cpd_cycle_label}. leave blank for no end date."
10
+
11
+ - if f.object.new_record?
12
+ - latest_cycle = Effective::CpdCycle.latest_cycle
13
+
14
+ - if latest_cycle.present?
15
+ = f.static_field :continue_from, value: latest_cycle,
16
+ hint: "The next #{cpd_cycle_label} will be carried forward from last one. Please make sure this #{cpd_cycle_label} is the most recent one."
17
+
18
+ = f.submit("Save and Create Next #{cpd_cycle_label.titleize}")
19
+
20
+ - if f.object.persisted?
21
+ = f.submit
@@ -0,0 +1,56 @@
1
+ - edit_path = effective_cpd.edit_admin_cpd_category_path(cpd_category)
2
+
3
+ = effective_form_with(model: [:admin, cpd_cycle], engine: true) do |f|
4
+ %h2= cpd_category
5
+ %p= cpd_category.body
6
+ %p= link_to 'Edit Category', edit_path, target: '_blank'
7
+
8
+ = f.fields_for :cpd_rules, cpd_cycle.rule_for(cpd_category) do |fc|
9
+ = fc.number_field :max_credits_per_cycle,
10
+ label: "Max #{cpd_credits_label} per #{cpd_cycle_label}",
11
+ hint: "The maximum number of #{cpd_credits_label} that may be earned in this category for this #{cpd_cycle_label}. Leave blank for no limit."
12
+
13
+ = fc.text_field :credit_description,
14
+ hint: "A simple description of the maximum #{cpd_credits_label} and carry forward policy of activities for this category"
15
+
16
+ = fc.check_box :unavailable, label: "Unavailable in this #{cpd_cycle_label}"
17
+
18
+ = f.submit
19
+
20
+ = effective_form_with(model: [:admin, cpd_cycle], engine: true) do |f|
21
+ %h2 Activities
22
+ - rules = cpd_category.cpd_activities.map { |activity| cpd_cycle.rule_for(activity) }
23
+
24
+ = f.fields_for :cpd_rules, rules do |fa|
25
+ - activity = fa.object.ruleable
26
+
27
+ = card do
28
+ .row
29
+ .col
30
+ %h5.card-title= activity
31
+ - if activity.body.present?
32
+ %p= activity.body
33
+
34
+ %p= link_to 'Edit Activity', edit_path, target: '_blank'
35
+
36
+ = f.static_field :amount_label, value: activity.amount_label.presence || '-'
37
+ = f.static_field :amount2_label, value: activity.amount2_label.presence || '-'
38
+ = f.static_field :requires_upload_file, value: (activity.requires_upload_file ? 'Yes' : '-')
39
+
40
+ .col
41
+ = fa.text_field :formula, hint: cpd_rule_formula_hint(activity)
42
+
43
+ = fa.text_field :credit_description, label: "#{cpd_credits_label.titleize} description",
44
+ hint: "A simple description of the formula and its #{cpd_credits_label} calculation"
45
+
46
+ = fa.number_field :max_credits_per_cycle,
47
+ label: "Max #{cpd_credits_label} per #{cpd_cycle_label}",
48
+ hint: 'leave blank for no limit'
49
+
50
+ = fa.number_field :max_cycles_can_carry_forward,
51
+ label: "Max #{cpd_cycles_label} can carry forward",
52
+ hint: "leave blank for no limit"
53
+
54
+ = fa.check_box :unavailable, label: "Unavailable in this #{cpd_cycle_label}"
55
+
56
+ = f.submit
@@ -0,0 +1,6 @@
1
+ = tabs do
2
+ = tab 'Statement' do
3
+ = render('effective/cpd_statements/cpd_statement', cpd_statement: cpd_statement)
4
+
5
+ = tab 'Logs' do
6
+ = render_inline_datatable(cpd_statement.log_changes_datatable)
@@ -0,0 +1,70 @@
1
+ - url = (cpd_statement_activity.persisted? ? effective_cpd.cpd_statement_cpd_statement_activity_path(cpd_statement_activity.cpd_statement, cpd_statement_activity) : effective_cpd.cpd_statement_cpd_statement_activities_path(cpd_statement_activity.cpd_statement))
2
+ - readonly = cpd_statement_activity.locked? || local_assigns[:readonly]
3
+
4
+ = effective_form_with(model: cpd_statement_activity, url: (readonly ? '#' : url), remote: true, class: 'cpd-statement-activity-form') do |f|
5
+ - statement = cpd_statement_activity.cpd_statement
6
+ - activity = cpd_statement_activity.cpd_activity
7
+ - rule = statement.cpd_cycle.rule_for(activity)
8
+
9
+ %h3= activity
10
+
11
+ - if activity.body.present?
12
+ = activity.body
13
+
14
+ - if cpd_statement_activity.is_carry_over? && (current_user.id == cpd_statement_activity.cpd_statement.user_id)
15
+ .alert.alert-warning
16
+ This activity is read-only because it was carried forward from
17
+ = cpd_statement_activity.original.cpd_statement.cpd_cycle
18
+
19
+ .row.my-3
20
+ .col-8
21
+ %strong #{cpd_credits_label.titleize} Calculation
22
+ %br
23
+ = rule.credit_description
24
+
25
+ .col-2.text-center
26
+ - if f.object.persisted?
27
+ %strong= cpd_credits_label.titleize
28
+ %br
29
+ - if f.object.reduced_messages.present?
30
+ %span{title: f.object.reduced_messages.values.join("\n\n")}= "#{f.object.score} *"
31
+ - else
32
+ = f.object.score.to_i
33
+
34
+ .col-2.text-center
35
+ - if f.object.persisted?
36
+ %strong Carry Forward
37
+ %br
38
+ = f.object.carry_forward.to_i
39
+
40
+ .row
41
+ .col
42
+ - if activity.amount_label.present?
43
+ = f.number_field :amount, label: activity.amount_label.titleize, required: true, readonly: readonly, disabled: readonly
44
+
45
+ - if activity.amount2_label.present?
46
+ = f.number_field :amount2, label: activity.amount2_label.titleize, required: true, readonly: readonly, disabled: readonly
47
+
48
+ - if activity.amount_label.blank? && activity.amount2_label.blank?
49
+ = f.hidden_field :amount, value: 1
50
+ %p One (1) #{activity}
51
+
52
+ - unless readonly && f.object.files.blank?
53
+ = f.file_field :files, label: 'Supporting Documents', required: activity.requires_upload_file?, disabled: readonly
54
+
55
+ .col
56
+ = f.text_area :description, placeholder: 'Please provide any additional information about this activity', readonly: readonly, disabled: readonly
57
+
58
+ - unless readonly
59
+ = f.hidden_field :cpd_category_id
60
+ = f.hidden_field :cpd_activity_id
61
+
62
+ = f.submit do
63
+ = f.save 'Save Activity'
64
+
65
+ %div{style: 'position: absolute; left: 0;'}
66
+ - if f.object.new_record?
67
+ = link_to('Back', '#', class: 'btn btn-secondary', 'data-cpd-back-activity': true)
68
+ - else
69
+ - url = effective_cpd.cpd_statement_cpd_statement_activity_path(statement, cpd_statement_activity)
70
+ = link_to('Delete', url, class: 'btn btn-danger', 'data-confirm': "Really delete?", 'data-method': :delete)
@@ -0,0 +1,64 @@
1
+ .cpd-statement-activities
2
+ .row
3
+ .col-8
4
+ .col-2.score
5
+ %strong= cpd_credits_label.titleize
6
+ .col-2.carry-forward
7
+ %strong Carry Forward
8
+
9
+ - effective_cpd_categories.each do |category|
10
+ - statement_activities = cpd_statement.cpd_statement_activities.select { |a| a.cpd_category_id == category.id }
11
+ - next if statement_activities.blank?
12
+
13
+ - rule = cpd_statement.cpd_cycle.rule_for(category)
14
+
15
+ .statement-activity-category
16
+ %h3
17
+ #{category}
18
+ %small
19
+ = cpd_statement.score_per_category[category.id].to_i
20
+ - if rule.max_credits_per_cycle.present?
21
+ = '/'
22
+ = rule.max_credits_per_cycle
23
+
24
+ .progress.my-2
25
+ - valuenow = cpd_statement.score_per_category[category.id]
26
+ - valuemax = (rule.max_credits_per_cycle || 1)
27
+ - width = ((valuenow * 100.0) / valuemax)
28
+
29
+ .progress-bar{role: 'progressbar', style: "width: #{width}%", 'aria-valuenow': valuenow, 'aria-valuemin': 0, 'aria-valuemax': valuemax}
30
+
31
+ - statement_activities.each do |statement_activity|
32
+ .statement-activity.mb-3
33
+ .statement-activity-content.row
34
+ .col-8
35
+ = link_to('#', 'data-cpd-edit-activity': true) do
36
+ = icon('plus-circle', class: 'small-1')
37
+ = statement_activity.cpd_activity
38
+ - if statement_activity.is_carry_over?
39
+ %br
40
+ %small carried forward from #{statement_activity.original_cycle}
41
+
42
+ .col-2.score
43
+ - if statement_activity.reduced_messages.present?
44
+ %span{title: statement_activity.reduced_messages.values.join("\n\n")}= "#{statement_activity.score} *"
45
+ - else
46
+ = statement_activity.score.to_i
47
+
48
+ .col-2.carry-forward
49
+ = statement_activity.carry_forward.to_i
50
+
51
+ .statement-activity-form.row{style: 'display: none;'}
52
+ .col
53
+ .border.px-3
54
+ = render('effective/cpd_statement_activities/form', cpd_statement_activity: statement_activity, readonly: local_assigns[:readonly])
55
+
56
+ %hr
57
+
58
+ .row
59
+ .col-8
60
+ %h4 Total #{cpd_credits_label} in statement
61
+ .col-2.score
62
+ %h4= cpd_statement.score.to_i
63
+ .col-2.carry-forward
64
+ %h4= cpd_statement.carry_forward.to_i
@@ -0,0 +1,39 @@
1
+ = vertical_tabs do
2
+ .statement-activity-content.tab-pane
3
+ -# The javascript will load the .statement-activity-form content into here
4
+
5
+ - effective_cpd_categories.each do |category|
6
+ - rule = cpd_statement.cpd_cycle.rule_for(category)
7
+ - next if rule.unavailable?
8
+
9
+ = tab(category) do
10
+ %h3
11
+ #{category}
12
+ %small
13
+ = cpd_statement.score_per_category[category.id].to_i
14
+ - if rule.max_credits_per_cycle.present?
15
+ = '/'
16
+ = rule.max_credits_per_cycle
17
+
18
+ .mb-3
19
+ %strong Description
20
+ = category.body
21
+
22
+ .mb-3
23
+ %strong #{cpd_credits_label.titleize} Calculation
24
+ %br
25
+ = rule.credit_description
26
+
27
+ %div
28
+ %strong Select an Activity to Continue
29
+
30
+ %ol
31
+ - category.cpd_activities.each do |activity|
32
+ - next if cpd_statement.cpd_cycle.rule_for(activity).unavailable?
33
+
34
+ %li
35
+ = link_to(activity, '#', 'data-cpd-show-activity': true)
36
+
37
+ .statement-activity-form{style: 'display: none;'}
38
+ - cpd_statement_activity = cpd_statement.cpd_statement_activities.new(cpd_category: category, cpd_activity: activity)
39
+ = render('effective/cpd_statement_activities/form', cpd_statement_activity: cpd_statement_activity)
@@ -0,0 +1,6 @@
1
+ %h2 Agreements
2
+ = f.check_box :confirm_read, label: "Yes, I have read the above content and agreements"
3
+ = f.check_box :confirm_factual, label: "Yes, I declare all provided information to be factual and complete"
4
+
5
+ %h2 Resume
6
+ = f.file_field :files, label: 'Attach resume', hint: 'Please attach your resume or other CPD related documents'
@@ -0,0 +1,5 @@
1
+ = card(cpd_statement.cpd_cycle.to_s + ' Statement') do
2
+ = render('effective/cpd_statements/summary', cpd_statement: cpd_statement)
3
+
4
+ = card('Activities') do
5
+ = render('effective/cpd_statements/activities', cpd_statement: cpd_statement, readonly: true)
@@ -0,0 +1,37 @@
1
+ .row
2
+ .col-3
3
+ = render_wizard_sidebar(resource)
4
+
5
+ - cpd_cycle = resource.cpd_cycle
6
+ - start_at = cpd_cycle.start_at
7
+ - end_at = cpd_cycle.end_at
8
+ - last_3_cycles = Effective::CpdCycle.sorted.where('start_at <= ?', start_at).last(3)
9
+ - last_3_scores = Effective::CpdStatement.where(cpd_cycle: last_3_cycles, user: resource.user).sum(&:score)
10
+
11
+ %table.table.mt-4
12
+ %tbody
13
+ - if end_at.present? && !resource.completed?
14
+ %tr{title: "#{cpd_cycle} is available #{cpd_cycle.available_date}"}
15
+ %td
16
+ %h4= ((end_at - Time.zone.now) / 1.day).to_i
17
+
18
+ %td days left to submit
19
+
20
+ %tr
21
+ %td
22
+ %h4= resource.score.to_i
23
+
24
+ %td
25
+ - if cpd_cycle.required_score.to_i > 0
26
+ #{cpd_credits_label} out of #{cpd_cycle.required_score} required
27
+ - else
28
+ #{cpd_credits_label} in current #{cpd_cycle_label}
29
+
30
+ %tr
31
+ %td
32
+ %h4= last_3_scores.to_i
33
+
34
+ %td #{cpd_credits_label} in last 3 #{cpd_cycles_label} (including this #{cpd_cycle_label})
35
+
36
+ .col-9
37
+ = yield
@@ -0,0 +1,36 @@
1
+ %table.table
2
+ %tbody
3
+ %tr
4
+ %th Name
5
+ %td
6
+ = cpd_statement.user
7
+ %br
8
+ %small= mail_to cpd_statement.user.email
9
+
10
+ - if request.path.start_with?('/admin') && respond_to?(:edit_admin_user_path)
11
+ %tr
12
+ %th User
13
+ %td= link_to(cpd_statement.user, edit_admin_user_path(cpd_statement.user))
14
+
15
+ - if cpd_statement.completed?
16
+ %tr
17
+ %th Completed
18
+ %td= cpd_statement.completed_at.strftime('%F %H:%M')
19
+
20
+ %tr
21
+ %th= cpd_cycle_label.titleize
22
+ %td= cpd_statement.cpd_cycle
23
+ %tr
24
+ %th Total #{cpd_credits_label.titleize}
25
+ %td= cpd_statement.score
26
+ %tr
27
+ %th Carry Forward
28
+ %td= cpd_statement.carry_forward
29
+ %tr
30
+ %th Attachments
31
+ %td
32
+ - if cpd_statement.files.blank?
33
+ None
34
+ - else
35
+ - cpd_statement.files.each do |file|
36
+ %div= link_to(file.filename, url_for(file), target: '_blank')
@@ -0,0 +1,25 @@
1
+ #cpd-statement-activities
2
+ .row
3
+ .col-3
4
+ .col-9
5
+ %h1= resource.cpd_cycle
6
+
7
+ .activities-index
8
+ = render('layout') do
9
+ - if resource.cpd_cycle.all_steps_content.present?
10
+ .mb-2= resource.cpd_cycle.all_steps_content
11
+
12
+ - if resource.cpd_cycle.activities_content.present?
13
+ .mb-2= resource.cpd_cycle.activities_content
14
+
15
+ - if resource.cpd_statement_activities.present?
16
+ = render('activities', cpd_statement: resource)
17
+
18
+ .mt-3= link_to 'Add Activity', '#', 'data-cpd-new-activity': true, class: 'btn btn-primary'
19
+
20
+ = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
21
+ = f.hidden_field :current_step
22
+ = f.submit 'Save and Continue', center: true
23
+
24
+ .activities-new{style: 'display: none;'}
25
+ = render('activities_new', cpd_statement: resource)