Skip to content

Commit

Permalink
Merge pull request #60 from it3s/relations
Browse files Browse the repository at this point in the history
Relations
  • Loading branch information
LuizArmesto committed Aug 8, 2014
2 parents f749cfa + fce4268 commit 2bb8b9a
Show file tree
Hide file tree
Showing 49 changed files with 1,286 additions and 38 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

# secrets
/config/secrets.yml
/config/initializers/local_settings.rb

# code coverage
/coverage
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ gem 'tinymce-rails' # tinymce wysiwyg editor
gem 'tinymce-rails-langs' # tinymce language pack
gem "jquery-fileupload-rails" # jquery-fielupload plugin
gem 'jquery-ui-rails' # jqueryUI
gem 'ejs' # js templating for js test fixtures
gem 'meppit-map-rails', :github => 'it3s/meppit-map-rails' # our beloved map

# gem 'turbolinks' # speed page loading
Expand Down Expand Up @@ -73,7 +74,6 @@ group :test do
gem 'factory_girl_rails' # mock objects
gem 'capybara' # acceptance tests
gem 'poltergeist' # phantomjs driver
gem 'ejs' # js templating for js test fixtures
gem 'database_cleaner' # improved database cleaning for tests
gem 'simplecov', '~> 0.7.1', require: false # coverage report
gem 'coveralls', require: false # use coveralls with travisCI
Expand Down
3 changes: 3 additions & 0 deletions app/assets/javascripts/application.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
#= require jquery_ujs
#= require jquery.remotipart
#= require jquery.ui.autocomplete
#= require jquery.ui.datepicker
#= require jquery.ui.datepicker-pt-BR
#= require jquery.infinitescroll
#= require jquery.cookie

#= require base

#= require_tree ./templates
#= require_tree ./components

onReady = ->
Expand Down
4 changes: 3 additions & 1 deletion app/assets/javascripts/components/autocomplete.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ App.components.autocomplete = (container) ->

onSelect: (event, ui) ->
value = ui.item?.id || ""
@autocompleteTarget().val(value)
target = @autocompleteTarget()
target.val(value)
target.trigger 'change'

startPlugin: ->
_this = this
Expand Down
30 changes: 30 additions & 0 deletions app/assets/javascripts/components/dateRange.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
App.components.dateRange = (container) ->
{
container: container

init: ->
@from = @container.find('[data-date-range=from]')
@to = @container.find('[data-date-range=to]')

@startPlugin()

locale: ->
_locale = $('body').data 'locale'
$.datepicker.regional[_locale] || $.datepicker.regional[""]

startPlugin: ->
@from.datepicker
changeMonth: true
changeYear: true
dateFormat: 'yy-mm-dd'
onClose: (selectedDate) => @to.datepicker('option', 'minDate', selectedDate)

@to.datepicker
changeMonth: true
changeYear: true
dateFormat: 'yy-mm-dd'
onClose: (selectedDate) => @from.datepicker('option', 'maxDate', selectedDate)

$.datepicker.setDefaults @locale()
}

5 changes: 5 additions & 0 deletions app/assets/javascripts/components/editor.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ App.components.editor = (container) ->
getLocale: ->
$('body').data('locale').replace('-', '_')

onEditorChange: (ed)->
App.mediator.publish 'tinymce:changed', {id: @container.attr('id'), content: ed.target.getContent()}

options: ->
_.extend {}, @defaults, {
selector: "textarea##{@container.attr('id')}"
language: @getLocale()
height: @container.attr('data-height') or @defaults.height
setup: (ed) =>
ed.on 'change', _.debounce(@onEditorChange).bind(this)
}

init: ->
Expand Down
7 changes: 7 additions & 0 deletions app/assets/javascripts/components/money.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#= require jquery.maskMoney

App.components.money = (container) ->
container: container

init: ->
@container.maskMoney thousands: ''
167 changes: 167 additions & 0 deletions app/assets/javascripts/components/relationsManager.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
metadataForm = ->
{
template: JST['templates/relationMetadata']

init: (opts) ->
@index = opts.index
@el = $ @template(opts)
@findFields()
@status = 'hidden'
@bindEvents()
this

show: ->
@el.slideDown('fast')
@status = "active"

hide: ->
@el.slideUp('fast')
@status = "hidden"

findFields: ->
@fields = {}
_.each ['description', 'start_date', 'end_date', 'currency', 'amount'], (key) =>
@fields[key] = @el.find(".metadata_#{key}")

onChange: ->
App.mediator.publish 'relationMetadata:changed', @index

getValue: ->
vals = {}
_.each @fields, (el, key) -> vals[key] = el.val()
vals

setValue: (entry) ->
_.each ['description', 'start_date', 'end_date', 'currency', 'amount'], (key) =>
if key is 'amount'
@fields[key].val entry[key]?.toFixed(2)
else
@fields[key].val entry[key]


bindEvents: ->
_.each @fields, (el, key) =>
switch key
when 'description'
App.mediator.subscribe 'tinymce:changed', (evt, data) =>
if data.id is el.attr('id')
el.val data.content
@onChange()
when 'amount'
el.on "change keyup paste", _.debounce(@onChange.bind(this), 100)
else
el.change _.debounce(@onChange.bind(this), 100)
}

relationItem = ->
{
template: JST['templates/relationItem']

init: (opts) ->
@index = opts.index
@el = $ @template(opts)
@addMetadataForm(opts)
@findElements()
@bindEvents()
this

addMetadataForm: (opts) ->
@metadata = metadataForm().init(opts)
@el.find('.metadata-container').append @metadata.el

findElements: ->
@targetEl = @el.find('.relation_target')
@typeEl = @el.find('.relation_type')
@idEl = @el.find('.relation_id')

onRemove: (evt) ->
evt.preventDefault()

@el.fadeOut 200, =>
App.mediator.publish 'relationItem:removed', @index
@el.remove()

getId: ->
if @idEl.val().length > 0 then @idEl.val() else null

getValue: ->
if @targetEl.val().length > 0 && @typeEl.val().length > 0
{id: @getId(), target: {id: @targetEl.val()}, type: @typeEl.val(), metadata: @metadata.getValue()}
else
null

setValue: (entry)->
@targetEl.val(entry.target.id)
@el.find('.relation_target_autocomplete').val(entry.target.name)
@typeEl.val(entry.type)
@idEl.val(entry.id)
@metadata.setValue(entry.metadata)

onChange: ->
App.mediator.publish 'relationItem:changed' if @getValue()

metadataChanged: (evt, index) ->
@onChange() if index is @index

toggleMetadata: (evt)->
evt.preventDefault()
if @metadata.status is 'hidden' then @metadata.show() else @metadata.hide()

bindEvents: ->
@el.find('.relation-remove-btn').click @onRemove.bind(this)
@el.find('.relation-metadata-btn').click @toggleMetadata.bind(this)

@targetEl.change @onChange.bind(this)
@typeEl.change @onChange.bind(this)

App.mediator.subscribe 'relationMetadata:changed', @metadataChanged.bind(this)
}

App.components.relationsManager = (container) ->
{
container : container
itemsContainer: container.find('.relations-list')
addButton : container.find('.add-new-relation')
relationsInput: container.find('.relations-value')
items : []
counter : 0

init: ->
@data = @container.data 'relationsManager'
@loadData() if @relationsInput.val().length > 0
@addItem() # always show an empty new entry
@listen()

loadData: ->
entries = JSON.parse @relationsInput.val()
_.each entries, (entry) =>
item = @addItem()
item.setValue(entry)

addItem: ->
item = relationItem().init _.extend({}, @data, {index: @counter++})
@items.push item
@itemsContainer.append(item.el)
App.mediator.publish 'components:start', item.el
item

onAdd: (evt) ->
evt.preventDefault()
@addItem()

onRemove: (evt, index) ->
@items[index] = null
@onChange()

onChange: ->
vals = []
_.each @items, (item) ->
vals.push item.getValue() if item && item.getValue()
@relationsInput.val JSON.stringify(vals)

listen: ->
@addButton.click @onAdd.bind(this)
App.mediator.subscribe 'relationItem:removed', @onRemove.bind(this)
App.mediator.subscribe 'relationItem:changed', @onChange.bind(this)

}
26 changes: 26 additions & 0 deletions app/assets/javascripts/components/togglePanel.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
App.components.togglePanel = (container) ->
{
container: container

init: ->
@panel = $("#{@container.attr('href')}")
@status = 'hidden'
@bindEvents()

bindEvents: ->
@container.on 'click', @toggle.bind(this)

show: ->
@panel.slideDown('fast')
@status = 'visible'

hide: ->
@panel.slideUp('fast')
@status = 'hidden'

toggle: (evt) ->
evt.preventDefault()
if @status is 'visible' then @hide() else @show()


}
21 changes: 21 additions & 0 deletions app/assets/javascripts/templates/relationItem.jst.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div class="relation-item" data-rel-index="<%= index %>">
<input type="hidden" name="relation_id" class="relation_id" />

<select name="relations_type_<%= index%>" class="relation_type" >
<option value=""> </option>
<% _.each(options, function(opt) { %>
<option value="<%= opt[1] %>"><%= opt[0] %></option>
<% }); %>
</select>

<input type="hidden" name="relations_target_<%= index%>" class="relation_target"
id="relation_target_<%= index %>-autocomplete"/>
<input type="text" class="relation_target_autocomplete" placeholder="<%= autocomplete_placeholder %>"
data-components="autocomplete"
data-component-options='{"name":"relation_target_<%= index %>","url":"<%= autocomplete_url %>"}' />

<a href="#" class="relation-metadata-btn" title="<%= metadata_title %>"><i class="fa fa-book"></i></a>
<a href="#" class="relation-remove-btn" title="<%= remove_title %>"><i class="fa fa-trash-o"></i></a>

<div class="metadata-container"></div>
</div>
27 changes: 27 additions & 0 deletions app/assets/javascripts/templates/relationMetadata.jst.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<div class="relation-metadata">
<h3><%= metadata_title %>:</h3>
<textarea id="metadata_description_<%= index %>" class="metadata_description tinymce"
data-components="editor" data-height="100">
</textarea>
<div class="wrapper" data-components="dateRange">
<div class="time-field inline-field">
<label for="metadata_start_date_<%=index%>"><%= start_date_label %></label>
<input type="text" class="metadata_start_date" data-date-range="from" />
</div>
<div class="time-field inline-field">
<label for="metadata_end_date_<%=index%>"><%= end_date_label %></label>
<input type="text" class="metadata_end_date" data-date-range="to" />
</div>
<div class="currency-field inline-field">
<select class="metadata_currency">
<option value="usd" title="US dollar">U$</option>
<option value="eur" title="Euro">&euro;</option>
<option value="brl" title="Real">R$</option>
</select>
</div>
<div class="amount-field inline-field">
<label for="metadata_amount_<%=index%>"><%= amount_label %></label>
<input type="text" class="metadata_amount" data-components="money" />
</div>
</div>
</div>
2 changes: 2 additions & 0 deletions app/assets/stylesheets/application.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
@import "jquery.qtip";
@import "jquery.tagsinput";
@import "jquery.ui.autocomplete-scss";
@import "jquery.ui.datepicker-scss";
@import "jquery.ui.tabs";
@import "meppit-map";

Expand Down Expand Up @@ -52,3 +53,4 @@
@import "geo_data";
@import "maps";
@import "versions";
@import "relations";
Loading

0 comments on commit 2bb8b9a

Please sign in to comment.