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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3564d479c782c49da3714d46d516fbc535e40cfa
4
+ data.tar.gz: 19904bda0bb747bfd063e87683cdb12391ec7de3
5
+ SHA512:
6
+ metadata.gz: bea91bf31935f7321f8a5e2aadfa5e7eceef27781eb5abbc70bbb346e5dffafc03adc46a80c2d39932e93126222e495f1a70e3e54d7003e25d2068ae65c6c287
7
+ data.tar.gz: 3157ae4e247df688200788bfac820cec812a1199c5fbb43217c24e82893902b24bac5e94dba651d34369331fd93b02008e7bb77778b8fb8257b8594477203f17
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ .rspec
4
+ Gemfile.lock
@@ -0,0 +1 @@
1
+ 2.1.4
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in biola_wcms_components.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Ryan Hall
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,74 @@
1
+ # Biola WCMS Components
2
+
3
+ This provides reusable UX components for our differnet WCMS projects
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'biola_wcms_components'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install biola_wcms_components
18
+
19
+ #### Dependencies
20
+
21
+ * ace-rails-ap
22
+ * coffee-rails
23
+ * sass-rails
24
+ * slim
25
+ * rails (this is not an explicit dependency but I haven't tested it using anything else)
26
+
27
+ ## Usage
28
+
29
+ ### Rails > 3.1
30
+
31
+ Include the following in `application.css.scss`.
32
+
33
+ @import "biola-wcms-components";
34
+
35
+ Include the following in `application.js.coffee`.
36
+
37
+ #= require biola-wcms-components
38
+
39
+
40
+ ### Components
41
+
42
+ In your view file, you will render `wcms_component("path/to/component", options)`
43
+
44
+ Example:
45
+
46
+ = wcms_component "forms/presentation_data_editor",
47
+ schema: @generic_object.presentation_data_template.schema,
48
+ data: @generic_object.presentation_data,
49
+ form: f,
50
+ embedded_image_url: create_embedded_images_url
51
+
52
+ Currently, look in `app/views/wcms_components` for available components.
53
+
54
+
55
+ #### Other requirements
56
+
57
+ * `current_user` - should be defined an ApplicationController. Should return user when logged in
58
+
59
+ #### Configuration
60
+
61
+ Create a new file called `/config/initializers/biola_wcms_components.rb`
62
+
63
+ BiolaWcmsComponents.configure do |config|
64
+ config.default_redactor_buttons = ['bold', 'italic', 'orderedlist', 'unorderedlist']
65
+ end
66
+
67
+
68
+ ## Contributing
69
+
70
+ 1. Fork it
71
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
72
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
73
+ 4. Push to the branch (`git push origin my-new-feature`)
74
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
File without changes
@@ -0,0 +1,15 @@
1
+ #= require ace/ace
2
+ #= require ace/mode-yaml
3
+ #= require ace/mode-json
4
+ #= require ace/worker-json
5
+ #
6
+ # Handlebars and typeahead are needed for the person-lookup component
7
+ #= require handlebars
8
+ #= require typeahead
9
+ #
10
+ #= require redactor
11
+ #= require redactor_fullscreen
12
+ #
13
+ #= require_tree ./configuration
14
+ #= require_tree ./components
15
+ #= require_self
@@ -0,0 +1,20 @@
1
+ $(document).ready ->
2
+ $('.ace_json_editor').each ->
3
+ editor_area = document.createElement('div')
4
+ this.appendChild(editor_area)
5
+
6
+ # Initialize Ace Editor
7
+ editor = ace.edit(editor_area)
8
+ editor.getSession().setMode("ace/mode/json")
9
+ editor.getSession().setTabSize(2)
10
+ editor.getSession().setUseWrapMode(true);
11
+ editor.setPrintMarginColumn(800)
12
+ editor.setOptions({
13
+ minLines: 8,
14
+ maxLines: Infinity
15
+ });
16
+
17
+ textarea = $(this).children('textarea').hide()
18
+ editor.getSession().setValue textarea.val()
19
+ editor.getSession().on "change", ->
20
+ textarea.val editor.getSession().getValue()
@@ -0,0 +1,29 @@
1
+ $(document).ready ->
2
+ if $('.person-lookup').length > 0
3
+ people_search_url = $('.person-lookup').first().data('lookup-url')
4
+
5
+ peopleSearch = new Bloodhound(
6
+ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value')
7
+ queryTokenizer: Bloodhound.tokenizers.whitespace
8
+ # The prefetch url returns a list of all the faculty
9
+ prefetch: people_search_url
10
+ remote: people_search_url + '?q=%QUERY'
11
+ )
12
+
13
+ peopleSearch.initialize()
14
+ $('.person-lookup .typeahead').typeahead null,
15
+ name: 'people-search'
16
+ displayKey: (person) ->
17
+ person.name + " <#{person.email || person.id}>"
18
+ highlight: true
19
+ source: peopleSearch.ttAdapter()
20
+ templates:
21
+ empty: '<div class="tt-empty-message">No one found with that name</div>'
22
+ suggestion: Handlebars.compile(
23
+ '<span class="image" style="background-image: url({{image}})" ></span>' +
24
+ '<span class="name">{{name}}</span> <span class="affiliations">{{affiliations}}</span>'
25
+ )
26
+
27
+ # We need to submit the ID through a hidden input for improved lookup.
28
+ $('.person-lookup .typeahead').on "typeahead:selected typeahead:autocompleted", (e,datum) ->
29
+ $('.person-lookup .hidden-person-id').val datum.id
@@ -0,0 +1,69 @@
1
+ $(document).ready ->
2
+ if $('#presentation_data_editor').length > 0
3
+
4
+ # Disable all framework fields, otherwise they will save on submit
5
+ $('.array_wrapper .framework').find('input, textarea').each ->
6
+ this.disabled = true
7
+
8
+ # Delete an array item when you click the delete button
9
+ $('.array_wrapper').on 'click', '.delete_array_item', ->
10
+ $(this).parents('.array_item').remove()
11
+ false
12
+
13
+ # Add an new array item from the last array_item
14
+ $('.array_wrapper .add_array_item').click ->
15
+ last_item = $(this).siblings('.array_item').last()
16
+ framework = $(this).siblings('.array_item.framework').last()
17
+ new_item = framework.clone()
18
+ new_item.removeClass("framework")
19
+
20
+ # Get array number for last item
21
+ last_number = last_item.find('input, textarea').first().attr('id').match(/\d+/)
22
+ new_number = +last_number[0] + 1
23
+
24
+ # Loop through each element and enable it.
25
+ # They have to be disabled in the framework form so they don't get submitted
26
+ new_item.find('input, textarea').each ->
27
+ this.id = this.id.replace(/\d+/, new_number)
28
+ this.disabled = false
29
+ this.value = ""
30
+
31
+ # Append to DOM after last item
32
+ last_item.after(new_item)
33
+
34
+ # Setup redactor for new item
35
+ # NOTE: This is the reason I am copying the 'framework' item above,
36
+ # because redactor is already setup for the other items.
37
+ # I explicitly exclude redactor setup from items nested under 'framework'
38
+ setupRedactorEditorsUnder(new_item)
39
+
40
+ false
41
+
42
+
43
+
44
+
45
+
46
+ ##############################
47
+ # Setup drag-drop image upload
48
+ ##############################
49
+ uploadImage = (file, input) ->
50
+ fileUploader.sendFileToServer file, 'embedded_image', ((url) ->
51
+ input.value = url
52
+ ), ->
53
+ alert('There was a problem uploading the image')
54
+
55
+ $('#presentation_data_editor').on 'dragover', 'input.drop-image-uploader', (e) ->
56
+ event.preventDefault()
57
+ event.stopPropagation()
58
+ $(this).addClass('dragging')
59
+
60
+ $('#presentation_data_editor').on 'dragleave', 'input.drop-image-uploader', (e) ->
61
+ event.preventDefault()
62
+ event.stopPropagation()
63
+ $(this).removeClass('dragging')
64
+
65
+ $('#presentation_data_editor').on 'drop', 'input.drop-image-uploader', (e) ->
66
+ event.preventDefault()
67
+ event.stopPropagation()
68
+ uploadImage(e.originalEvent.dataTransfer.files[0], this)
69
+ $(this).removeClass('dragging')
@@ -0,0 +1,39 @@
1
+ # This is depricated. We will keep this around until we have moved everything over to the new
2
+ # plain data form editor.
3
+
4
+ $(document).ready ->
5
+ $('.ace_yaml_editor').each ->
6
+ editor_area = document.createElement('div')
7
+ this.appendChild(editor_area)
8
+
9
+ # Initialize Ace Editor
10
+ editor = ace.edit(editor_area)
11
+ editor.getSession().setMode("ace/mode/yaml")
12
+ editor.getSession().setTabSize(2)
13
+ editor.setPrintMarginColumn(800)
14
+ editor.setOptions({
15
+ minLines: 8,
16
+ maxLines: Infinity
17
+ });
18
+
19
+ textarea = $(this).children('textarea').hide()
20
+ editor.getSession().setValue textarea.val()
21
+ editor.getSession().on "change", ->
22
+ textarea.val editor.getSession().getValue()
23
+
24
+
25
+ # Setup drag-drop image upload
26
+ editor.container.addEventListener 'dragover', (e) =>
27
+ e.preventDefault()
28
+ e.stopPropagation()
29
+
30
+ editor.container.addEventListener 'dragleave', (e) =>
31
+ e.preventDefault()
32
+ e.stopPropagation()
33
+
34
+ editor.container.addEventListener 'drop', (e) =>
35
+ e.preventDefault()
36
+ e.stopPropagation()
37
+ fileUploader.sendFileToServer e.dataTransfer.files[0], 'embedded_image', (url) ->
38
+ editor.insert('"' + url + '"')
39
+
@@ -0,0 +1,55 @@
1
+ # In order to use you must first set up an uploader
2
+ # Example:
3
+ # fileUploader.addUploader('embedded_image', "http://api.example.com/uploader");
4
+ #
5
+ # Then you can send a file to that uploader whenever you are ready.
6
+ # Example:
7
+ # fileUploader.sendFileToServer file, 'embedded_image', ((url) ->
8
+ # alert 'success!'
9
+ # ), ->
10
+ # alert 'error :('
11
+ #
12
+
13
+
14
+ window.fileUploader ||= {
15
+ uploaders: {}
16
+ }
17
+
18
+ fileUploader.addUploader = (key, url) ->
19
+ fileUploader.uploaders[key] = url
20
+
21
+ fileUploader.sendFileToServer = (file, urlKey, successCallback, errorCallback) ->
22
+ if fileUploader.uploaders[urlKey]
23
+ form_data = new FormData()
24
+ form_data.append('file', file)
25
+ form_data.append('authenticity_token', $('[name=csrf-token').attr('content'))
26
+
27
+ xhr = new XMLHttpRequest()
28
+ xhr.open "POST", fileUploader.uploaders[urlKey]
29
+
30
+ # complete
31
+ xhr.onreadystatechange = $.proxy(->
32
+ if xhr.readyState is 4
33
+ data = xhr.responseText
34
+ data = data.replace(/^\[/, "")
35
+ data = data.replace(/\]$/, "")
36
+ json = undefined
37
+ try
38
+ json = ((if typeof data is "string" then $.parseJSON(data) else data))
39
+ catch err
40
+ json = error: true
41
+
42
+ if json.error
43
+ if errorCallback
44
+ errorCallback()
45
+ else
46
+ alert('There was a problem uploading the file')
47
+ else
48
+ successCallback(json.filelink)
49
+ return
50
+ , this)
51
+ xhr.send form_data
52
+
53
+ else
54
+ alert('Uploader is not configured.')
55
+
@@ -0,0 +1,65 @@
1
+ setupRedactor = (obj) ->
2
+ # Default Options
3
+ options =
4
+ minHeight: 200
5
+ allowedTags: ['p', 'br']
6
+ buttons: []
7
+
8
+ # Add any custom data attributes to the default options
9
+ if obj.data('linkable') # in case you want to support links without explicitly giving a link button.
10
+ options.allowedTags = $.merge(options.allowedTags, 'a')
11
+ if data = obj.data('buttons')
12
+ buttons = data.split(' ')
13
+ options.buttons = $.merge(options.buttons, buttons)
14
+ options.allowedTags = $.merge(options.allowedTags, buttonsToTags(buttons))
15
+ if tuned_data = obj.data('formatting')
16
+ formatting = tuned_data.split (' ')
17
+ options.formatting = tuned_data.split (' ')
18
+ if options.allowedTags.indexOf('a') >= 0
19
+ options.convertLinks = true;
20
+ if options.buttons.indexOf('fullscreen') >= 0
21
+ options.plugins = ['fullscreen']
22
+
23
+ # Uniq all arrays
24
+ options.buttons = $.unique(options.buttons)
25
+ if formatting
26
+ options.formatting = $.unique(options.formatting)
27
+ options.allowedTags = $.unique(options.allowedTags)
28
+
29
+ # Initialize redactor
30
+ obj.redactor(options)
31
+
32
+
33
+ button_to_tag_mapping =
34
+ bold: ['b', 'strong']
35
+ italic: ['i', 'em']
36
+ link: ['a']
37
+ orderedlist: ['ol', 'li']
38
+ table: ['table', 'tr', 'tbody', 'td']
39
+ unorderedlist: ['ul', 'li']
40
+
41
+ buttonsToTags = (buttons) ->
42
+ tags = []
43
+ $.each buttons, (index, value) ->
44
+ if mapping = button_to_tag_mapping[value]
45
+ tags = $.merge(tags, mapping)
46
+ tags
47
+
48
+
49
+ window.setupRedactorEditorsUnder = (obj) ->
50
+ # Initialize redactor on items with the class 'redactor'
51
+ $(obj).find("textarea.redactor:enabled").each (i) ->
52
+ # Don't setup redactor if the textarea inherits from a "framework" item.
53
+ # framework items are hidden and are used to add new items to a form array.
54
+ # If it inherits from .redactor-box that means it has already been initialized.
55
+ unless $(this).parents('.framework, .redactor-box').length > 0
56
+ setupRedactor($(this))
57
+
58
+
59
+ $(document).ready ->
60
+ # Run on startup
61
+ setupRedactorEditorsUnder('body')
62
+
63
+ # Run when modals open
64
+ $(".modal").on "shown.bs.modal", (e) ->
65
+ setupRedactorEditorsUnder('.modal')
@@ -0,0 +1,43 @@
1
+ //===============================================
2
+ // Toggle-able media queries and old IE helper
3
+ // See: http://jakearchibald.github.io/sass-ie/
4
+ //===============================================
5
+ $fix-mqs: false !default;
6
+ $old-ie: false !default;
7
+ $max-width-extreme:9999px;
8
+
9
+ @mixin respond($min-width:0, $max-width:$max-width-extreme, $orientation:null) {
10
+ // If we're outputting for a fixed media query set...
11
+ @if $fix-mqs {
12
+ // ...and if we should apply these rules...
13
+ @if $fix-mqs >= $min-width and $fix-mqs <= $max-width {
14
+ // ...output the content the user gave us.
15
+ @content;
16
+ }
17
+ }
18
+ @else {
19
+ // Otherwise, output it using a regular media query
20
+ $query:'screen';
21
+
22
+ @if $min-width > 0 {
23
+ $query:$query + " and (min-width:#{$min-width})";
24
+ }
25
+ @if $max-width < $max-width-extreme {
26
+ $query:$query + " and (max-width:#{$max-width})";
27
+ }
28
+ @if $orientation {
29
+ $query:$query + " and (orientation:#{$orientation})";
30
+ }
31
+
32
+ @media #{$query} {
33
+ @content;
34
+ }
35
+ }
36
+ }
37
+
38
+ @mixin old-ie {
39
+ // Only use this content if we're dealing with old IE
40
+ @if $old-ie {
41
+ @content;
42
+ }
43
+ }