diff --git a/Gemfile b/Gemfile index 669fe74..8de2e0a 100644 --- a/Gemfile +++ b/Gemfile @@ -38,6 +38,7 @@ gem 'carrierwave_backgrounder' # delegate uploads to background jobs gem 'mini_magick' # image processing for uploaders gem 'fog' # upload images to amazon S3 gem 'remotipart' # enable ajax file uploads on remote forms +gem 'kaminari' # paginator group :doc do gem 'sdoc', :require => false diff --git a/Gemfile.lock b/Gemfile.lock index 4b43449..a9e8cd1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -160,6 +160,9 @@ GEM json (1.8.1) jwt (0.1.11) multi_json (>= 1.5) + kaminari (0.16.0) + actionpack (>= 3.0.0) + activesupport (>= 3.0.0) konacha (3.2.0) actionpack (>= 3.1, < 5) capybara @@ -372,6 +375,7 @@ DEPENDENCIES jquery-fileupload-rails jquery-rails jquery-ui-rails + kaminari konacha letter_opener letter_opener_web diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 3221368..f4c3755 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -3,6 +3,7 @@ #= require jquery_ujs #= require jquery.remotipart #= require jquery.ui.autocomplete +#= require jquery.infinitescroll #= require base diff --git a/app/assets/javascripts/components/list.js.coffee b/app/assets/javascripts/components/list.js.coffee new file mode 100644 index 0000000..4b1a7b6 --- /dev/null +++ b/app/assets/javascripts/components/list.js.coffee @@ -0,0 +1,25 @@ +App.components.list = (container) -> + { + container: container + list: container.find("ul.list") + + infiniteScrollDefaults: + navSelector: "nav.pagination" + nextSelector: "nav.pagination a[rel=next]" + itemSelector: ".list .list-item" + prefill: on + dataType: "html" + + init: -> + @handleOptions() + @startInfiniteScroll(@infiniteScrollOptions) + + handleOptions: -> + data = @container.data('list') ? {} + @infiniteScrollOptions = _.defaults(data.scroll ? {}, @infiniteScrollDefaults) + if @infiniteScrollOptions['behavior'] is 'local' + @infiniteScrollOptions.binder ?= container + + startInfiniteScroll: (opts) -> + @list.infinitescroll opts + } diff --git a/app/assets/stylesheets/_settings.css.scss b/app/assets/stylesheets/_settings.css.scss index e2279b2..50afb43 100644 --- a/app/assets/stylesheets/_settings.css.scss +++ b/app/assets/stylesheets/_settings.css.scss @@ -77,10 +77,12 @@ $text-link-visited-color: #004047; $stick-color-bg: $white; $stick-color-shadow: $meppit-blue; +$list-item-separator-color: $soft-grey; + // Typography $main-font: Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif; $highlight-font: Cambria, Georgia, serif; -$base-font-size: 14px; +$base-font-size: 13px; $secondary-content-font-size: 0.85em; diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index 7e96f26..b1a4b6e 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -34,6 +34,7 @@ @import "shared/stick"; @import "shared/tabs"; @import "shared/counters"; +@import "shared/lists"; @import "sessions/sign_in"; diff --git a/app/assets/stylesheets/geo_data.css.scss b/app/assets/stylesheets/geo_data.css.scss index c38d653..089efa2 100644 --- a/app/assets/stylesheets/geo_data.css.scss +++ b/app/assets/stylesheets/geo_data.css.scss @@ -1,4 +1,4 @@ -.page.data-view { +.site-page.data-view { .data-logo { width: 50px; height:50px; diff --git a/app/assets/stylesheets/shared/_counters.css.scss b/app/assets/stylesheets/shared/_counters.css.scss index 040bb24..64af88a 100644 --- a/app/assets/stylesheets/shared/_counters.css.scss +++ b/app/assets/stylesheets/shared/_counters.css.scss @@ -25,22 +25,45 @@ display: inline-block; margin: 0 5px 0 0; vertical-align: middle; - font-size: 1.7em; + font-size: 1.8em; } .counter-value { display: inline-block; vertical-align: middle; text-align: center; - font-size: 0.8em; + font-size: 0.9em; line-height: 1em; em { display: block; color: $text-color; font-weight: bold; - font-size: 1.2em; + font-size: 1.3em; } } + + &.small, &.medium { + margin: 0 0 0 5px; + font-size: 0.9em; + + a { + padding: 5px; + } + + i { + font-size: 1em; + } + + .counter-value { + min-width: 1.5em; + text-align: inherit; + } + } + + &.medium { + font-size: 1.15em; + } + } } diff --git a/app/assets/stylesheets/shared/_lists.css.scss b/app/assets/stylesheets/shared/_lists.css.scss new file mode 100644 index 0000000..42f926f --- /dev/null +++ b/app/assets/stylesheets/shared/_lists.css.scss @@ -0,0 +1,81 @@ +nav.pagination { display: none; } // We are using infinite scroll + +.list-item { + clear: both; + padding: 15px 0; + border-bottom: 1px solid $list-item-separator-color; + + &:hover { background: $dark-white; } + + a, a:hover { text-decoration: none; } + + .item-checkbox { float: left; } + + .item-avatar { + display: block; + float: left; + margin: 0 10px 0 0; + background: $soft-grey; + color: #fff; + text-align: center; + + i { margin: 2px 0; } + } + + &.small { + .item-avatar, img { + font-size: 30px; + width: 32px; + height: 32px; + border-radius: 5px; + } + + .item { + width: 400px; + } + + .item-excerpt { font-size: 0.95em; } + } + + &.big { + .item-checkbox { margin: 22px 15px; } + + .item-avatar, img { + font-size: 54px; + width: 64px; + height: 64px; + border-radius: 7px; + } + + .item { + min-height: 64px; + width: 620px; + } + } + + .item { + float: left; + + .item-title { + font-family: inherit; + font-size: 1.15em; + color: $text-link-color; + margin: 0 0 2px; + } + + .item-excerpt { color: $text-color; } + } + + &.map { + .item-avatar { background: $meppit-maps-color; } + .item .item-title { color: $meppit-maps-color; } + } + &.data { + .item-avatar { background: $meppit-data-color; } + .item .item-title { color: $meppit-data-color; } + } + + .item-controls { + .counters { margin: 8px 0; } + } +} diff --git a/app/assets/stylesheets/shared/_page.css.scss b/app/assets/stylesheets/shared/_page.css.scss index 5d91492..e4bbda8 100644 --- a/app/assets/stylesheets/shared/_page.css.scss +++ b/app/assets/stylesheets/shared/_page.css.scss @@ -1,4 +1,4 @@ -.page { +.site-page { @include span-columns($page-columns); .side-pane { @@ -13,4 +13,20 @@ font-size: 1.6em; letter-spacing: -0.02em; } + &.full { + @include span-columns(12); + + .side-pane { + @include span-columns(3 of 12); + } + + .central-pane { + @include span-columns(9 of 12); + } + + h1.name { + font-size: 1.6em; + letter-spacing: -0.02em; + } +} } diff --git a/app/assets/stylesheets/shared/_stick.css.scss b/app/assets/stylesheets/shared/_stick.css.scss index c85027e..ef82a52 100644 --- a/app/assets/stylesheets/shared/_stick.css.scss +++ b/app/assets/stylesheets/shared/_stick.css.scss @@ -3,6 +3,6 @@ z-index: 2000; } -.page .stick > * { +.site-page .stick > * { box-shadow: $stick-color-shadow 0px 5px 3px -3px; } diff --git a/app/assets/stylesheets/shared/_toolbar.css.scss b/app/assets/stylesheets/shared/_toolbar.css.scss index 8ebc775..eeb635c 100644 --- a/app/assets/stylesheets/shared/_toolbar.css.scss +++ b/app/assets/stylesheets/shared/_toolbar.css.scss @@ -3,6 +3,7 @@ .toolbar-buttons { background: url('imgs/toolbar-bg.png') no-repeat right top; + padding: 0 5px; min-height: 430px; float: left; } diff --git a/app/assets/stylesheets/users/_profile.css.scss b/app/assets/stylesheets/users/_profile.css.scss index e2010f5..2b83d9c 100644 --- a/app/assets/stylesheets/users/_profile.css.scss +++ b/app/assets/stylesheets/users/_profile.css.scss @@ -1,4 +1,4 @@ -.page.user-profile { +.site-page.user-profile { // left pane .avatar { @@ -27,7 +27,7 @@ // Central pane .main-title { float:left; - max-width: 435px; + max-width: 425px; } .location { @@ -47,6 +47,11 @@ margin: 0 0 20px; } + .involvement > div { + overflow-y: auto; + height: 400px; + } + &.edit { .field { padding: 0; diff --git a/app/controllers/geo_data_controller.rb b/app/controllers/geo_data_controller.rb index 66288ab..75401b1 100644 --- a/app/controllers/geo_data_controller.rb +++ b/app/controllers/geo_data_controller.rb @@ -3,6 +3,14 @@ class GeoDataController < ApplicationController before_action :require_login, :only => [:edit, :update] before_action :find_data, :only => [:show, :edit, :update] + def index + @list = GeoData.page(params[:page]).per(params[:per]) + respond_to do |format| + format.html { render :layout => !request.xhr? } + format.js + end + end + def show end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 10f07fc..b7c1470 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,7 +2,7 @@ class UsersController < ApplicationController include PasswordResets before_action :require_login, :only => [:edit, :update] - before_action :find_user, :only => [:show, :edit, :update] + before_action :find_user, :only => [:show, :edit, :update, :contributions] before_action :is_current_user, :only => [:edit, :update] def new @@ -49,6 +49,13 @@ def update end end + def contributions + respond_to do |format| + format.html { render :layout => !request.xhr? } + format.js + end + end + private def user_params diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 5f09062..06904ed 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -79,4 +79,35 @@ def counters_list(obj, only=:all) available_counters = counters.select {|key, counter| obj.respond_to? counter[:method] } only == :all ? available_counters.values() : only.map {|name| available_counters[name] } end + + def contributions_list(obj) + #TODO: get real objects + list = [ + GeoData.find(1), + GeoData.find(1), + User.find(2), + GeoData.find(1), + User.find(2), + GeoData.find(1), + GeoData.find(1), + GeoData.find(1), + GeoData.find(1), + GeoData.find(1), + User.find(2), + GeoData.find(1) + ] + Kaminari.paginate_array(list).page(params[:page]).per(5) + end + + def object_type(obj) + if obj.kind_of? User + :user + elsif obj.kind_of? GeoData + :data + #elsif obj.kind_of? Map + #:map + else + :unknown + end + end end diff --git a/app/models/user.rb b/app/models/user.rb index 2215abf..375b300 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -40,12 +40,12 @@ def geojson_properties end def followers_count - # TODO + #TODO refactor to concern 0 end def maps_count - # TODO + #TODO refactor to concern 0 end end diff --git a/app/views/geo_data/_geo_data.html.erb b/app/views/geo_data/_geo_data.html.erb new file mode 100644 index 0000000..e0f4eac --- /dev/null +++ b/app/views/geo_data/_geo_data.html.erb @@ -0,0 +1 @@ +<%= render 'shared/lists/item', :object => geo_data, :size => local_assigns[:size], :checkbox => local_assigns[:checkbox], :control => :counters %> diff --git a/app/views/geo_data/edit.html.erb b/app/views/geo_data/edit.html.erb index 4adb411..22c4791 100644 --- a/app/views/geo_data/edit.html.erb +++ b/app/views/geo_data/edit.html.erb @@ -1,6 +1,6 @@ <%= render 'shared/toolbar', :object => @data, :only => data_tools(@data) %> -
+
<%= remote_form_for @data do |f| %>
diff --git a/app/views/geo_data/index.html.erb b/app/views/geo_data/index.html.erb new file mode 100644 index 0000000..3bde14f --- /dev/null +++ b/app/views/geo_data/index.html.erb @@ -0,0 +1,9 @@ +
+
+

<%= raw t('geo_data.list.title', :count => "#{@list.total_count}") %>

+
<%= paginate @list, :remote => true %>
+
    + <%= render @list, :checkbox => true %> +
+
+
diff --git a/app/views/geo_data/index.js.erb b/app/views/geo_data/index.js.erb new file mode 100644 index 0000000..0c4bc56 --- /dev/null +++ b/app/views/geo_data/index.js.erb @@ -0,0 +1,2 @@ +$('#geodata-list').html('<%= escape_javascript render(@list, :checkbox => true) %>'); +$('#geodata-pagination').html('<%= escape_javascript(paginate(@list, :remote => true).to_s) %>'); diff --git a/app/views/geo_data/show.html.erb b/app/views/geo_data/show.html.erb index a8aba4f..2a04f6f 100644 --- a/app/views/geo_data/show.html.erb +++ b/app/views/geo_data/show.html.erb @@ -1,6 +1,6 @@ <%= render 'shared/toolbar', :object => @data, :only => data_tools(@data) %> -
+
diff --git a/app/views/shared/lists/_item.html.erb b/app/views/shared/lists/_item.html.erb new file mode 100644 index 0000000..b0292b8 --- /dev/null +++ b/app/views/shared/lists/_item.html.erb @@ -0,0 +1,42 @@ +<% type = object_type object %> +<% size = local_assigns[:size] || :big %> +
  • +
    + <% if local_assigns[:checkbox] %> +
    + +
    + <% end %> + +
    + <% if object[:avatar] %> + <%= image_tag object[:avatar].thumb.url %> + <% else %> + <% if type == :map %> + <%= icon :globe %> + <% elsif type == :data %> + <%= icon :'map-marker' %> + <% elsif type == :user %> + <%= icon :user %> + <% else %> + <%= icon :question %> + <% end %> + <% end %> +
    +
    +
    + +

    <%= truncate object[:name], length: (size == :small ? 55 : 85) %>

    +

    <%= truncate(object[:description] || object[:about_me], length: (size == :small ? 130 : 300)) %>

    +
    + <% if size == :big and object.respond_to? :tags %> + <%= render 'shared/tags', :tags => object[:tags] %> + <% end %> +
    +
    + <% if local_assigns[:control] == :counters %> + <%= render 'shared/counters', :object => object, :size => (size == :small ? :small : :medium) %> + <% end %> +
    +
    +
  • diff --git a/app/views/users/_contributions.html.erb b/app/views/users/_contributions.html.erb new file mode 100644 index 0000000..fedc7a5 --- /dev/null +++ b/app/views/users/_contributions.html.erb @@ -0,0 +1,7 @@ +<% list = contributions_list @user %> +
    <%= paginate list, :remote => true, :params => paginate_params %>
    +
      + <% list.each do |item| %> + <%= render 'shared/lists/item', :object => item, :size => :small, :control => :counters %> + <% end %> +
    diff --git a/app/views/users/contributions.html.erb b/app/views/users/contributions.html.erb new file mode 100644 index 0000000..8d173c0 --- /dev/null +++ b/app/views/users/contributions.html.erb @@ -0,0 +1,30 @@ +<%= render 'shared/toolbar', :object => @user, :only => user_tools(@user)%> + + diff --git a/app/views/users/contributions.js.erb b/app/views/users/contributions.js.erb new file mode 100644 index 0000000..c7c0861 --- /dev/null +++ b/app/views/users/contributions.js.erb @@ -0,0 +1 @@ +$('#contributions').html('<%= escape_javascript render('users/contributions', :object => @user, :paginate_params => {:controller => 'users', :action => 'contributions'}) %>'); diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 822eaab..1723d8f 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -1,9 +1,9 @@ <%= render 'shared/toolbar', :object => @user, :only => user_tools(@user)%> -