Skip to content

Commit

Permalink
Merge pull request #82 from it3s/import
Browse files Browse the repository at this point in the history
Import
  • Loading branch information
LuizArmesto committed Oct 8, 2014
2 parents a4bf1c6 + 7d87e29 commit 60ce41c
Show file tree
Hide file tree
Showing 40 changed files with 876 additions and 12 deletions.
41 changes: 41 additions & 0 deletions app/assets/javascripts/components/importEdit.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

App.components.importEdit = ->
errMessage: """
<div class="err"><i class="fa fa-exclamation-triangle"></i><%= msg %></div>
"""

attributes: ->
submitBtn: @container.find('.submit-btn')
mapInput: @container.find('#map-autocomplete')
errsDiv: @container.find('.validation-errors')

initialize: ->
@on @attr.submitBtn, 'click', @onSubmit

onSubmit: (evt) ->
@cleanErrors()
unless @isValid()
@showErrors()
evt.preventDefault()

isValid: ->
@hasMap() && @allEntriesAreValid()

hasMap: ->
_val = @attr.mapInput.val()
_val && _val.length > 0

allEntriesAreValid: ->
@container.find('li.parsed-data.invalid').length is 0

cleanErrors: ->
@attr.errsDiv.html ""

showErrors: ->
if !@hasMap()
_tpl = _.template(@errMessage, msg: I18n.imports.errors.map)
@attr.errsDiv.append _tpl

if !@allEntriesAreValid()
_tpl = _.template(@errMessage, msg: I18n.imports.errors.invalid)
@attr.errsDiv.append _tpl
16 changes: 16 additions & 0 deletions app/assets/javascripts/components/importUploader.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

App.components.importUploader = ->
_.extend App.components.uploader(), {

buttonLabel: I18n.uploader.import

afterInitialize: ->
@method = if @attr.update then 'PATCH' else 'POST'

onDone: (e, data) ->
setTimeout( =>
window.location = data.result.redirect if data.result.redirect
@reset()
, 200)

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ App.components.pictureUploader = ->

onDone: (e, data) ->
setTimeout( =>
console.log data.result
@addPictureThumb data.result
App.utils.flashMessage(data.result.flash)
@reset()
Expand Down
6 changes: 4 additions & 2 deletions app/assets/javascripts/components/uploader.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ uploaderTemplate = """
App.components.uploader = ->
buttonLabel: I18n.uploader.select_image

method: 'PATCH'

attributes: ->
_uploader = $ _.template(uploaderTemplate, buttonLabel: @buttonLabel)
{
Expand All @@ -20,8 +22,8 @@ App.components.uploader = ->
initialize: ->
@render()
@on @attr.button, 'click', (evt) => @container.trigger 'click'
@startPlugin()
@afterInitialize?()
@startPlugin()

render: ->
@attr.field.hide()
Expand All @@ -30,7 +32,7 @@ App.components.uploader = ->
startPlugin: ->
@container.fileupload
url: @attr.url
type: 'PATCH'
type: @method
dataType: 'json'
add: @onAdd.bind(this)
done: @onDone.bind(this)
Expand Down
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@
@import "activities";
@import "notifications";
@import "pictures";
@import "import";
4 changes: 4 additions & 0 deletions app/assets/stylesheets/core/_mixins.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
@include button($meppit-dark-blue, lighten($meppit-dark-blue, 10%), $white, $border: $border);
}

@mixin blue-button-with-border {
@include blue-button($border: darken($meppit-dark-blue, 20%));
}

@mixin red-button {
@include button($dark-red, $red, $white, $border: $dark-red);
}
Expand Down
187 changes: 187 additions & 0 deletions app/assets/stylesheets/import.css.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
.import-modal {
@include modal;

h2 {
text-align: center;
margin-bottom: 20px;
}

.explanation {
margin-bottom: 20px;
}

.example {
margin: 20px 0 30px;
}

.upload-file-wrapper {
text-align: center;

.error {
display: block;
color: $dark-red;
}
}

.upload-button {
@include blue-button-with-border;
padding: 15px 80px;
}
}

.imports {
.title {
margin-bottom: 40px;

h1 { text-align: center; }
}
.import-file, .import-action {
margin-bottom: 20px;

label {
font-weight: bold;
display: inline-block;
width: 250px;
}
}
.uploader {
display: inline-block;

.upload-button {
@include blue-button-with-border;
padding: 5px 10px;
width: auto;
}
}

.import-action {
position: relative;

.ui-autocomplete-input { width: 250px; }

.submit-btn {
@include blue-button-with-border;
display: inline-block;
position: absolute;
right: 0;
top: -5px;
}
}

.validation-errors {
margin: 10px 0;

.err {
color: $dark-red;
padding: 10px;
background: lighten($soft-red, 25%);
border-radius: 4px;
margin-bottom: 5px;

i { margin-right: 10px; }
}
}

.already-imported {
font-weight: bold;
padding: 20px;
text-align: center;
color: $dark-green;
background-color: lighten($soft-green, 35%);
border-radius: 4px;
margin-bottom: 20px;

i { margin-right: 10px; }
}

.parsed-data-list {

.parsed-data {
position: relative;
padding: 10px;
margin-bottom: 10px;
border-radius: 4px;
width: 100%;
background-color: lighten($meppit-light-blue, 5%);

.icon {
margin-right: 5px;
}

.number {
font-weight: bold;
margin-right: 10px;
color: $grey;
}

&.valid {
border: solid 1px $dark-green;
.icon { color: $dark-green }
}
&.invalid {
border: solid 1px $dark-red;
.icon { color: $dark-red }
}

.see-table-button {
@include button;
display: inline-block;
position: absolute;
right: 10px;
top: 5px;
padding: 4px 8px;
}

.data-preview {
display: none;
}

.section-label {
display: block;
margin: 20px 0 10px;
font-weight: bold;
}

.raw-line .line, .json-table {
padding: 10px;
background: $main-color-bg;
border-radius: 4px;
border: solid 1px $ultra-soft-grey;
}

.invalid-attrs {
margin-top: 10px;
margin-left: -2px;
font-size: 0.9em;
color: $dark-red;
opacity: 0.8;

.err-key { font-weight: bold; }
}
}
}
}
.list-item.import {
.item-avatar {
font-size: 30px;
width: 32px;
height: 32px;
border-radius: 5px;
}

.import-status {
float: right;
padding: 5px;
color: white;
border-radius: 4px;
width: 150px;
text-align: center;
}

&.imported-true {
.item-avatar, .import-status { background-color: $dark-green; }
}
&.imported-false {
.item-avatar, .import-status { background-color: $dark-red; }
}
}
60 changes: 60 additions & 0 deletions app/controllers/imports_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
class ImportsController < ApplicationController

before_action :require_login, except: [:example]
before_action :find_import, only: [:edit, :update, :load]
before_action :is_current_user, only: [:edit, :update, :load]


def create
@import = Import.new import_params
save_import
end

def edit
@parsed_data = @import.parse_source
end

def update
@import.source = params[:import][:source]
save_import
end

def example
send_data example_csv , filename: t("import.example_filename")
end

def load
map_id = params[:map].to_i
loaded = @import.load_to_map! map_id
flash[:notice] = t("import.edit.load.#{ loaded ? 'success' : 'error' }")
redirect_to map_path(map_id)
end

private

def example_csv
values = Import.csv_headers.map { |key| t "import.example_value.#{key}" }
"#{ Import.csv_headers.join(',') }\n#{ values.join(',') }"
end

def import_params
{source: params[:import][:source], user: current_user}
end

def find_import
@import = Import.find params[:id]
end

def save_import
if @import.valid? && @import.save
render json: {redirect: edit_import_path(@import)}
else
render json: {errors: @import.errors.messages}, status: :unprocessable_entity
end
end

def is_current_user
redirect_to(root_path, notice: t('access_denied')) if @import.user != current_user
end

end
2 changes: 1 addition & 1 deletion app/controllers/pictures_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def success_json
end

def picture_params
{ image: params[:picture], author: current_user, content: @content }
{ image: params[:picture][:image], author: current_user, content: @content }
end

def find_content
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class UsersController < ApplicationController
before_action :contributions_list, only: [:show]
before_action :following_list, only: [:show]
before_action :activities_list, only: [:show]
before_action :imports_list, only: [:show]

def new
@user = User.new
Expand Down Expand Up @@ -86,4 +87,8 @@ def following_list
def activities_list
@activities ||= paginate @user.try(:activities_performed), params[:activities_page]
end

def imports_list
@imports ||= paginate @user.try(:imports), params[:imports_page]
end
end
4 changes: 4 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,8 @@ def collection_location(collection)

OpenStruct.new(location: location, location_geojson: location.try(:to_json))
end

def show_imports?(user)
logged_in? && user == current_user && !@imports.empty?
end
end
Loading

0 comments on commit 60ce41c

Please sign in to comment.