biola_wcms_components 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +74 -0
  7. data/Rakefile +1 -0
  8. data/app/assets/images/.gitkeep +0 -0
  9. data/app/assets/javascripts/biola-wcms-components.js.coffee +15 -0
  10. data/app/assets/javascripts/components/forms/json_editor.js.coffee +20 -0
  11. data/app/assets/javascripts/components/forms/person_lookup.js.coffee +29 -0
  12. data/app/assets/javascripts/components/forms/presentation_data_editor.js.coffee +69 -0
  13. data/app/assets/javascripts/components/forms/yaml_editor.js.coffee +39 -0
  14. data/app/assets/javascripts/configuration/file_uploader.js.coffee +55 -0
  15. data/app/assets/javascripts/configuration/setup_redactor.js.coffee +65 -0
  16. data/app/assets/stylesheets/_mixins.scss +43 -0
  17. data/app/assets/stylesheets/_settings.scss +1 -0
  18. data/app/assets/stylesheets/biola-wcms-components.scss +11 -0
  19. data/app/assets/stylesheets/components/alerts/_message_list.scss +3 -0
  20. data/app/assets/stylesheets/components/forms/_person_lookup.scss +72 -0
  21. data/app/assets/stylesheets/components/forms/_presentation_data_editor.scss +38 -0
  22. data/app/assets/stylesheets/components/navigation/_site_nav.scss +24 -0
  23. data/app/helpers/wcms_components/alerts_helper.rb +41 -0
  24. data/app/helpers/wcms_components/component_helper.rb +9 -0
  25. data/app/helpers/wcms_components/navigation_helper.rb +32 -0
  26. data/app/views/wcms_components/alerts/_message_list.html.slim +8 -0
  27. data/app/views/wcms_components/forms/_json_editor.html.slim +13 -0
  28. data/app/views/wcms_components/forms/_person_lookup.html.slim +12 -0
  29. data/app/views/wcms_components/forms/_presentation_data_editor.html.slim +36 -0
  30. data/app/views/wcms_components/forms/_redactor_editor.html.slim +32 -0
  31. data/app/views/wcms_components/forms/_text_area.html.slim +13 -0
  32. data/app/views/wcms_components/forms/_yaml_editor.html.slim +16 -0
  33. data/app/views/wcms_components/navigation/_page_nav.html.slim +33 -0
  34. data/app/views/wcms_components/navigation/_site_nav.html.slim +38 -0
  35. data/app/views/wcms_components/shared/.gitkeep +0 -0
  36. data/app/views/wcms_components/shared/_embedded_image_uploader.html.slim +6 -0
  37. data/biola_wcms_components.gemspec +27 -0
  38. data/config/locales/en.yml +4 -0
  39. data/lib/biola_wcms_components.rb +22 -0
  40. data/lib/biola_wcms_components/configuration.rb +9 -0
  41. data/lib/biola_wcms_components/engine.rb +6 -0
  42. data/lib/biola_wcms_components/version.rb +3 -0
  43. data/lib/components/menu_block.rb +130 -0
  44. data/lib/components/presentation_data_editor.rb +199 -0
  45. data/vendor/assets/javascripts/handlebars.js +3750 -0
  46. data/vendor/assets/javascripts/redactor.js +8312 -0
  47. data/vendor/assets/javascripts/redactor_fullscreen.js +123 -0
  48. data/vendor/assets/javascripts/typeahead.js +11 -0
  49. data/vendor/assets/stylesheets/redactor.css +924 -0
  50. metadata +176 -0
@@ -0,0 +1 @@
1
+ $color-biola-red: #CC1122;
@@ -0,0 +1,11 @@
1
+ // External files
2
+ @import "../../../vendor/assets/stylesheets/redactor";
3
+
4
+ // Mixins and settings
5
+ @import "./settings";
6
+ @import "./mixins";
7
+
8
+ // Components
9
+ @import "./components/alerts/*";
10
+ @import "./components/forms/*";
11
+ @import "./components/navigation/*";
@@ -0,0 +1,3 @@
1
+ #message_list {
2
+ .alert { margin: 10px 0; }
3
+ }
@@ -0,0 +1,72 @@
1
+ .person-lookup {
2
+ .typeahead, .tt-query, .tt-hint {
3
+ width: 396px;
4
+ height: 34px;
5
+ padding: 8px 12px;
6
+ font-size: 15px;
7
+ line-height: 15px;
8
+ border: 1px solid #ccc;
9
+ -webkit-border-radius: 4px;
10
+ -moz-border-radius: 4px;
11
+ border-radius: 4px;
12
+ outline: none;
13
+ }
14
+
15
+ .tt-query {
16
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
17
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
18
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
19
+ }
20
+
21
+ .tt-hint {
22
+ color: #999
23
+ }
24
+
25
+ .tt-dropdown-menu {
26
+ text-align: left;
27
+ width: 422px;
28
+ margin-top: 12px;
29
+ padding: 8px 0;
30
+ background-color: #fff;
31
+ border: 1px solid #ccc;
32
+ border: 1px solid rgba(0, 0, 0, 0.2);
33
+ -webkit-border-radius: 4px;
34
+ -moz-border-radius: 4px;
35
+ border-radius: 4px;
36
+ -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
37
+ -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
38
+ box-shadow: 0 5px 10px rgba(0,0,0,.2);
39
+ }
40
+
41
+ .tt-suggestion, .tt-empty-message {
42
+ padding: 3px 20px;
43
+ font-size: 16px;
44
+ line-height: 24px;
45
+
46
+ .affiliations {
47
+ color: #999;
48
+ font-size: 12px;
49
+ }
50
+ .image {
51
+ height: 30px;
52
+ width: 26px;
53
+ margin-right: 10px;
54
+ margin-left: -5px;
55
+ display: inline-block;
56
+ vertical-align: middle;
57
+ background-size: cover;
58
+ background-position: center center;
59
+ background-color: #ddd;
60
+ }
61
+ }
62
+
63
+ .tt-suggestion.tt-cursor {
64
+ cursor: pointer;
65
+ color: #fff;
66
+ background-color: #0097cf;
67
+
68
+ .affiliations {
69
+ color: #fff;
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,38 @@
1
+ #presentation_data_editor {
2
+ margin-bottom: 20px;
3
+
4
+ > .nest .nest {
5
+ border-top: 1px solid #ddd;
6
+ border-left: 1px solid #ddd;
7
+ padding: 20px 0 0 20px;
8
+
9
+ h4 {
10
+ margin: 30px 0 5px 0;
11
+ }
12
+ }
13
+
14
+ // Wraps Array name and items
15
+ .array_wrapper {
16
+ margin-bottom: 20px;
17
+ }
18
+
19
+ .array_item {
20
+ border-bottom: 1px solid #ddd;
21
+ padding-bottom: 20px;
22
+ margin-bottom: 20px;
23
+
24
+ // Make the border touch the nested border
25
+ margin-left: -20px;
26
+ padding-left: 20px;
27
+
28
+ // Framework item doesn't get saved
29
+ // it is just there for building out new items
30
+ &.framework {
31
+ display: none;
32
+ }
33
+ }
34
+
35
+ .drop-image-uploader {
36
+ &.dragging { background-color: #deedff; }
37
+ }
38
+ }
@@ -0,0 +1,24 @@
1
+ #wcms_site_navigation {
2
+ background-color: #f3f3f3;
3
+ border-bottom: 1px solid #ddd;
4
+
5
+ a.top-nav-link {
6
+ display: inline-block;
7
+ padding: 10px 0 10px;
8
+ color: inherit;
9
+ }
10
+ .fa-angle-right {
11
+ padding: 0 10px;
12
+ }
13
+
14
+ .custom-dropdown {
15
+ .dropdown-toggle {
16
+ color: inherit;
17
+ }
18
+ .dropdown-menu > .active > a {
19
+ background: none;
20
+ color: black;
21
+ font-weight: bold;
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,41 @@
1
+ module WcmsComponents
2
+ module AlertsHelper
3
+ def all_alerts
4
+ flash_alerts + model_alerts
5
+ end
6
+
7
+ def flash_alerts
8
+ flash.map { |key,val| {type: key, message: val} }
9
+ end
10
+
11
+ def model_alerts(model = nil)
12
+ model ||= instance_variable_get("@#{controller_name.singularize}")
13
+
14
+ return [] if model.nil?
15
+
16
+ model.errors.full_messages.map { |msg| {type: :error, message: msg} }
17
+ end
18
+
19
+ def alert_icon(type)
20
+ case type.to_s.to_sym
21
+ when :error, :alert
22
+ 'fa fa-exclamation-circle'
23
+ when :warn, :warning
24
+ 'fa fa-warning'
25
+ else
26
+ 'fa fa-info-circle'
27
+ end
28
+ end
29
+
30
+ def alert_class(type)
31
+ case type.to_s.to_sym
32
+ when :error, :alert
33
+ 'alert-danger'
34
+ when :warn, :warning
35
+ 'alert-warning' # default yellow
36
+ else
37
+ 'alert-info'
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,9 @@
1
+ module WcmsComponents
2
+ module ComponentHelper
3
+
4
+ def wcms_component(slug, properties={})
5
+ render "wcms_components/#{slug}", properties
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ module WcmsComponents
2
+ module NavigationHelper
3
+
4
+ # Set class on active navigation items
5
+ def nav_link(text, path_helper)
6
+ # The router can't match against a relative root in the path
7
+ # so we need to strip it out with script_name: nil.
8
+ router_path = send(path_helper, script_name: nil)
9
+ real_path = send(path_helper)
10
+
11
+ recognized = ::Rails.application.routes.recognize_path(router_path)
12
+
13
+ if policy(recognized[:controller].classify.constantize).index? # make sure user has permission to index this controller
14
+ if recognized[:controller] == params[:controller] # && recognized[:action] == params[:action]
15
+ content_tag(:li, :class => "descendant active") do
16
+ link_to( text, real_path)
17
+ end
18
+ else
19
+ content_tag(:li, :class => "descendant") do
20
+ link_to( text, real_path)
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ # Gets used by the side menu / page navigation
27
+ def menu_block(html_options = {}, &block)
28
+ MenuBlock.new(self, html_options).render(&block)
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,8 @@
1
+ .container
2
+ - unless (alerts = all_alerts).empty?
3
+ #message_list
4
+ - alerts.each do |msg|
5
+ .alert class=alert_class(msg[:type]) data-type=msg[:type]
6
+ a.close data-dismiss="alert" href="#" ×
7
+ i> class=alert_icon(msg[:type])
8
+ = msg[:message]
@@ -0,0 +1,13 @@
1
+ ruby:
2
+ form ||= nil
3
+ attribute ||= nil
4
+ html_class ||= 'form-control json_editor'
5
+ value ||= nil
6
+ embedded_image_url ||= nil # should be the post url for creating new embedded images
7
+
8
+
9
+ = wcms_component("shared/embedded_image_uploader", embedded_image_url: embedded_image_url)
10
+
11
+ .ace_json_editor
12
+ = wcms_component("forms/text_area", {form: form, attribute: attribute, html_class: html_class, value: value})
13
+
@@ -0,0 +1,12 @@
1
+ ruby:
2
+ lookup_url ||= nil
3
+
4
+ - if lookup_url
5
+ .person-lookup data-lookup-url=lookup_url
6
+ = hidden_field_tag :person_id, '', class: 'hidden-person-id'
7
+ = text_field_tag :person_name, '', placeholder: 'First or last name', required: true, class: 'form-control typeahead'
8
+
9
+ - else
10
+ p
11
+ ' Please specify
12
+ code = ":lookup_url"
@@ -0,0 +1,36 @@
1
+ / Example:
2
+ / = wcms_component "forms/presentation_data_editor",
3
+ / schema: @generic_object.presentation_data_template.schema,
4
+ / data: @generic_object.presentation_data,
5
+ / form: f,
6
+ / embedded_image_url: create_embedded_images_url
7
+ /
8
+
9
+ ruby:
10
+ schema ||= []
11
+ presentation_data ||= {}
12
+ form ||= nil
13
+ embedded_image_url ||= nil # should be the post url for creating new embedded images
14
+
15
+ = wcms_component "shared/embedded_image_uploader",
16
+ embedded_image_url: embedded_image_url
17
+
18
+
19
+ / Link to toggle between simple and advanced editors
20
+ - if current_user.try(:admin?)
21
+ - if params[:edit_raw_data] == 'true'
22
+ = link_to('Simple Editor', params.merge(edit_raw_data: nil), class: 'pull-right')
23
+ - else
24
+ = link_to('Edit Raw Data', params.merge(edit_raw_data: true), class: 'pull-right')
25
+ .clearfix
26
+
27
+
28
+ - if params[:edit_raw_data] == 'true' && current_user.try(:admin?)
29
+ / Render JSON editor
30
+ = wcms_component 'forms/json_editor',
31
+ form: form,
32
+ attribute: :presentation_data_json
33
+
34
+ - else
35
+ / Render HTML for presentation data editor
36
+ = PresentationDataEditor.new(self, presentation_data, schema, form).render
@@ -0,0 +1,32 @@
1
+ / Example:
2
+ / = wcms_component("forms/redactor_editor", {form: f,
3
+ / attribute: :body,
4
+ / add_buttons: ['link'],
5
+ / })
6
+
7
+
8
+ ruby:
9
+ # Default Parameters
10
+ form ||= nil
11
+ attribute ||= nil # attribute name that the editor should be attached to
12
+ add_class ||= "" # string of additional classes that get appended to class
13
+ input_class ||= "form-control redactor #{add_class}"
14
+ value ||= nil # only used if form is nil
15
+
16
+ # Configure buttons
17
+ buttons ||= BiolaWcmsComponents.config.default_redactor_buttons
18
+ add_buttons ||= [] # adds to defaults
19
+ remove_buttons ||= [] # removes from default
20
+ buttons = Array(buttons) + Array(add_buttons) - Array(remove_buttons)
21
+ buttons << 'html_options' if current_user.try(:admin?)
22
+ buttons << 'fullscreen'
23
+
24
+ # Turn buttons into a string and make sure there are no duplicates
25
+ buttons = buttons.uniq.join(' ')
26
+
27
+
28
+
29
+ - if form
30
+ = form.text_area attribute, class: input_class, 'data-buttons' => buttons
31
+ - else
32
+ = text_area_tag attribute, value, class: input_class, 'data-buttons' => buttons
@@ -0,0 +1,13 @@
1
+ ruby:
2
+ form ||= nil
3
+ attribute ||= nil
4
+ html_class ||= 'form-control'
5
+ value ||= nil
6
+
7
+ html_options = {class: html_class}
8
+ html_options[:value] = value if value.present? # you don't want to pass value as an option if it is nil
9
+
10
+ - if form
11
+ = form.text_area attribute, html_options
12
+ - else
13
+ = text_area_tag attribute, value, html_options
@@ -0,0 +1,16 @@
1
+ ruby:
2
+ form ||= nil
3
+ attribute ||= nil
4
+ html_class ||= 'form-control'
5
+ value ||= nil
6
+ embedded_image_url ||= nil # should be the post url for creating new embedded images
7
+
8
+ # Set default value
9
+ # We have to do it this way in case value is an empty string (as opposed to nil).
10
+ value = value.presence || "---\n# YAML data goes here...\n"
11
+
12
+
13
+ = wcms_component("shared/embedded_image_uploader", embedded_image_url: embedded_image_url)
14
+
15
+ .ace_yaml_editor
16
+ = wcms_component("forms/text_area", {form: form, attribute: attribute, html_class: html_class, value: value})
@@ -0,0 +1,33 @@
1
+ / I'm going to wait to implement this one fully...
2
+ / The problem is going to be supporting submenus like on profile publisher
3
+ /
4
+ / Example:
5
+ / = wcms_component('navigation/page_menu', { menu_items: [ \
6
+ / {body: 'Profile', url: edit_academic_program_path(@academic_program, page: 'profile'), default: true },
7
+ / {body: 'Relationships', url: edit_academic_program_path(@academic_program, page: 'relationships') },
8
+ / {body: 'Concentrations', url: edit_academic_program_path(@academic_program, page: 'concentrations') },
9
+ / {body: 'Degree Requirements', url: edit_academic_program_path(@academic_program, page: 'degree_requirements') },
10
+ / {body: 'Requirement Sections', url: edit_academic_program_path(@academic_program, page: 'requirement_sections') },
11
+ / {body: 'Outcomes', url: edit_academic_program_path(@academic_program, page: 'outcomes') },
12
+ / {body: 'Attachments', url: edit_academic_program_path(@academic_program, page: 'attachments') },
13
+ / {body: 'Banner', url: edit_academic_program_path(@academic_program, page: 'banner') },
14
+ / {body: 'Presentation Data', url: edit_academic_program_path(@academic_program, page: 'presentation_data') },
15
+ / {body: 'History', url: edit_academic_program_path(@academic_program, page: 'activity_logs'), visible: policy(@academic_program).can_manage?(:activity_logs) },
16
+ / ]})
17
+ /
18
+
19
+
20
+
21
+ /---------------
22
+ / ON HOLD...
23
+ /---------------
24
+ / ruby:
25
+ / menu_items ||= []
26
+
27
+ / = menu_block(class: 'list-group-item') do |menu|
28
+ / - menu_items.each do |item|
29
+ / / It needs to be explicitly set to false to be hidden
30
+ / - unless item.visible == false
31
+ / = menu.add_item(item[:body], default: item[:default]) { item[:url] }
32
+
33
+
@@ -0,0 +1,38 @@
1
+ / Parameters
2
+ / menu: Array of hashes. This is what goes in the dropdown menu
3
+ / body: This is the link text
4
+ / url: This is where the link will go. Gets processed by url_for()
5
+ / crumbs: (optional) Array of hashes. These are the crumbs after the main menu
6
+ / add_crumbs: (optional) Array of hashes. These get pushed onto the default crumbs
7
+ /
8
+ / Example:
9
+ / = wcms_component('navigation/site_nav', { menu: [ \
10
+ / {body: 'Academic Programs', url: :academic_programs_path},
11
+ / {body: 'Schools', url: :schools_path},
12
+ / {body: 'ULOs', url: :university_learning_outcomes_path},
13
+ / ]})
14
+ /
15
+
16
+ ruby:
17
+ menu ||= []
18
+ crumbs ||= [{
19
+ body: controller_name.titleize,
20
+ url: {controller: controller_name, action: :index}
21
+ }]
22
+ crumbs += Array(add_crumbs) if defined?(add_crumbs)
23
+
24
+
25
+ #wcms_site_navigation
26
+ .container
27
+ - if menu.present?
28
+ .dropdown.custom-dropdown
29
+ a.dropdown-toggle href='#' data-toggle='dropdown' role='button' Menu
30
+ ul.dropdown-menu
31
+ - menu.each do |link|
32
+ = nav_link(link[:body], link[:url])
33
+ - else
34
+ = link_to 'Home', root_url, class: 'top-nav-link'
35
+
36
+ - crumbs.each do |crumb|
37
+ i class='fa fa-angle-right'
38
+ = link_to crumb[:body], crumb[:url], class: 'top-nav-link'