From 2481ec1aa501b8ca8502c88af4b8093a11391805 Mon Sep 17 00:00:00 2001 From: Muhammet Date: Mon, 17 Jul 2017 23:43:46 -0700 Subject: [PATCH 01/13] improvements --- app/assets/javascripts/application.js | 1 + app/controllers/users_controller.rb | 4 + app/helpers/application_helper.rb | 10 + app/views/campaign_users/_index.html.haml | 15 ++ app/views/campaigns/_stats.html.haml | 20 +- app/views/campaigns/_template_form.html.haml | 20 -- app/views/campaigns/index.html.haml | 82 ++++---- app/views/campaigns/new.html.haml | 55 +++--- app/views/campaigns/show.html.haml | 74 ++++--- .../email_templates/_email_template.html.haml | 17 ++ app/views/email_templates/index.html.haml | 56 +++--- app/views/email_templates/new.html.haml | 10 +- app/views/email_templates/show.html.haml | 15 +- app/views/inbox/_detail.html.haml | 70 +++---- app/views/inbox/detail.js.erb | 4 +- app/views/layouts/application.html.haml | 16 +- app/views/shared/_advanced_search.html.haml | 3 +- app/views/tags/_item_tags.html.haml | 22 ++- .../user_attributes/_attribute_row.html.haml | 6 + .../_attributes_table.html.haml | 33 ++-- app/views/user_attributes/_form.html.haml | 9 + app/views/user_attributes/_index.html.haml | 2 + app/views/user_attributes/create.js.erb | 2 +- app/views/user_attributes/index.html.haml | 14 +- app/views/users/index.html.haml | 182 +++++++++--------- app/views/users/new.html.haml | 34 ++-- app/views/users/show.html.haml | 20 ++ config/routes.rb | 2 +- 28 files changed, 425 insertions(+), 373 deletions(-) create mode 100644 app/views/campaign_users/_index.html.haml delete mode 100644 app/views/campaigns/_template_form.html.haml create mode 100644 app/views/email_templates/_email_template.html.haml create mode 100644 app/views/user_attributes/_attribute_row.html.haml create mode 100644 app/views/user_attributes/_form.html.haml create mode 100644 app/views/user_attributes/_index.html.haml create mode 100644 app/views/users/show.html.haml diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index ef33300..dd95a29 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -1,5 +1,6 @@ //= require jquery //= require jquery_ujs +//= require jquery-ui //= require bootstrap-sprockets //= require editable/bootstrap-editable //= require editable/rails diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 375de31..996b36c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -22,6 +22,10 @@ def new; end def import; end + def show + @user = current_account.users.find(params[:id]) + end + def create if params[:file].present? && params[:tags].present? diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c445302..77de2a2 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -7,4 +7,14 @@ def link_to_add_fields(name, f, type) end link_to(name, '#', class: 'add_fields', data: { id: id, fields: fields.delete("\n") }) end + + def xeditable?(arg) + true + end + + def page_title(title) + content_for :page_title do + title + end + end end diff --git a/app/views/campaign_users/_index.html.haml b/app/views/campaign_users/_index.html.haml new file mode 100644 index 0000000..763db73 --- /dev/null +++ b/app/views/campaign_users/_index.html.haml @@ -0,0 +1,15 @@ +%table.table.table-bordered + %thead + %tr + %th Campaign + %th Status + %th Tags + + %tbody + - user.campaign_users.each do |cu| + %tr + %td= link_to cu.campaign.name, cu.campaign + %td= cu.status + %td + %div{id: "CampaignUserTags-#{cu.id}"} + = render partial: 'tags/item_tags', locals: { item: cu } \ No newline at end of file diff --git a/app/views/campaigns/_stats.html.haml b/app/views/campaigns/_stats.html.haml index cb533d3..26edb8a 100644 --- a/app/views/campaigns/_stats.html.haml +++ b/app/views/campaigns/_stats.html.haml @@ -3,7 +3,7 @@ .col-md-2.col-sm-4.col-xs-6.tile_stats_count %span.count_top %i.fa.fa-user - Draft Emails + Draft .count= @stats['draft'] || 0 %span.count_bottom %i.green @@ -12,7 +12,7 @@ .col-md-2.col-sm-4.col-xs-6.tile_stats_count %span.count_top %i.fa.fa-user - Processed Emails + Processed .count.green= @stats['processed'] || 0 %span.count_bottom %i.green @@ -21,7 +21,7 @@ .col-md-2.col-sm-4.col-xs-6.tile_stats_count %span.count_top %i.fa.fa-user - Dropped Emails + Dropped .count= @stats['dropped'] || 0 %span.count_bottom %i.green @@ -30,7 +30,7 @@ .col-md-2.col-sm-4.col-xs-6.tile_stats_count %span.count_top %i.fa.fa-user - Delivered Emails + Delivered .count= @stats['delivered'] || 0 %span.count_bottom %i.green @@ -39,7 +39,7 @@ .col-md-2.col-sm-4.col-xs-6.tile_stats_count %span.count_top %i.fa.fa-user - Deferred Emails + Deferred .count= @stats['deferred'] || 0 %span.count_bottom %i.green @@ -50,7 +50,7 @@ .col-md-2.col-sm-4.col-xs-6.tile_stats_count %span.count_top %i.fa.fa-user - Bounced Emails + Bounced .count= @stats['bounce'] || 0 %span.count_bottom %i.green @@ -59,7 +59,7 @@ .col-md-2.col-sm-4.col-xs-6.tile_stats_count %span.count_top %i.fa.fa-user - Opened Emails + Opened .count.green= @stats['open'] || 0 %span.count_bottom %i.green @@ -68,7 +68,7 @@ .col-md-2.col-sm-4.col-xs-6.tile_stats_count %span.count_top %i.fa.fa-user - Clicked Emails + Clicked .count= @stats['click'] || 0 %span.count_bottom %i.green @@ -77,7 +77,7 @@ .col-md-2.col-sm-4.col-xs-6.tile_stats_count %span.count_top %i.fa.fa-user - Spamreport Emails + Spamreport .count= @stats['spamreport'] || 0 %span.count_bottom %i.green @@ -86,7 +86,7 @@ .col-md-2.col-sm-4.col-xs-6.tile_stats_count %span.count_top %i.fa.fa-user - Unsubscribed Emails + Unsubscribed .count= @stats['unsubscribe'] || 0 %span.count_bottom %i.green diff --git a/app/views/campaigns/_template_form.html.haml b/app/views/campaigns/_template_form.html.haml deleted file mode 100644 index 95c43b6..0000000 --- a/app/views/campaigns/_template_form.html.haml +++ /dev/null @@ -1,20 +0,0 @@ -- body = Tilt::ERBTemplate.new { "#{@campaign.email_template.body}" } -- subject = Tilt::ERBTemplate.new { "#{@campaign.email_template.subject}" } - -.x_panel - %h2 - .text-center - = subject.render(User.first).html_safe - .pull-right - = link_to 'Edit Template', edit_email_template_path(@campaign.email_template), class: 'btn btn-default btn-xs' - = body.render(User.first).html_safe - -= form_tag send_emails_campaign_path(@campaign), method: :post do - .actions.text-center - .col-md-6 - Select SMTP Settings - = select_tag 'smtp_id', options_for_select(current_account.smtp_settings.map{|ss| [ ss.provider, ss.id ]}, current_account.smtp_settings.default_for_campaigns.try(:id)), include_blank: false, class: 'form-control' - .col-md-6 - = submit_tag 'Send Campaign Emails', class: 'btn btn-success btn-block', data: { confirm: 'This email will send only to email addresses in draft status. Are you sure?' }, style: 'margin-top: 17px;' - -%hr \ No newline at end of file diff --git a/app/views/campaigns/index.html.haml b/app/views/campaigns/index.html.haml index 7a15be1..473011a 100644 --- a/app/views/campaigns/index.html.haml +++ b/app/views/campaigns/index.html.haml @@ -1,51 +1,37 @@ -%div - .page-title - .title_left - %h3 Listing Campaigns += page_title 'Campaigns' - .clearfix - .row - .col-md-12 - .x_panel - .x_title - %h2 Filter Campaigns - %ul.nav.navbar-right.panel_toolbox - %li - %a.collapse-link.pull-right - %i.fa.fa-chevron-up - .clearfix - .x_content - = render partial: 'shared/advanced_search', locals: { form_url: nil } +.x_panel + .x_title + %h4 Campaigns - .row - .col-md-12 - .x_panel - .x_title - %h2 Campaigns List - .clearfix - .x_content - %table.table.table-striped.projects - %thead - %tr - %th Name - %th Tags - %th Users Count - %th Sent Emails - %th Template - %th # - %tbody - - @campaigns.each do |campaign| - %tr - %td= campaign.name - %td - - campaign.tags.each do |tag| - %span.btn.btn-info.btn-xs - = tag - %td= campaign.users.count - %td= campaign.campaign_users.where.not(status: 'draft').count - %td - = link_to "##{campaign.email_template.id}", email_template_path(campaign.email_template), 'data-toggle': 'tooltip', 'data-placement': 'top', 'data-original-title': "#{campaign.email_template.subject}" - %td - = link_to 'Show', campaign, class: 'btn btn-sm btn-default' - = link_to 'Destroy', campaign, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-sm btn-danger' + .x_content + = render partial: 'shared/advanced_search', locals: { form_url: nil } + %hr/ + + %table.table.table-striped.table-bordered.table-hover + %thead + %tr + %th Name + %th Tags + %th Users Count + %th Sent Emails + %th Template + %th{width: 80} # + %tbody + - @campaigns.each do |campaign| + %tr + %td= campaign.name + %td + - campaign.tags.each do |tag| + %span.btn.btn-info.btn-xs + = tag + %td= campaign.users.count + %td= campaign.campaign_users.where.not(status: 'draft').count + %td + = link_to "##{campaign.email_template.id}", email_template_path(campaign.email_template), 'data-toggle': 'tooltip', 'data-placement': 'top', 'data-original-title': "#{campaign.email_template.subject}" + %td + = link_to campaign, class: 'btn btn-sm btn-default btn-xs' do + %fa.fa.fa-eye + = link_to campaign, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-sm btn-danger btn-xs' do + %fa.fa.fa-trash diff --git a/app/views/campaigns/new.html.haml b/app/views/campaigns/new.html.haml index cb0e4d1..79fe6b8 100644 --- a/app/views/campaigns/new.html.haml +++ b/app/views/campaigns/new.html.haml @@ -1,34 +1,31 @@ -.page-title - .title_left - %h3 New campaign - .col-md-6.x_panel - = form_for @campaign do |f| - - if @campaign.errors.any? - #error_explanation - %h2= "#{pluralize(@campaign.errors.count, "error")} prohibited this campaign from being saved:" - %ul - - @campaign.errors.full_messages.each do |msg| - %li= msg += page_title "New campaign" - = f.label :name - = f.text_field :name, class: 'form-control' +.x_panel + = form_for @campaign do |f| + - if @campaign.errors.any? + #error_explanation + %h2= "#{pluralize(@campaign.errors.count, "error")} prohibited this campaign from being saved:" + %ul + - @campaign.errors.full_messages.each do |msg| + %li= msg - %label - Tag List - = select_tag :tags, options_for_select(@all_tags.map{ |t| [t, t] }), { include_blank: false, class: 'select2 form-control', multiple: true } + = f.label :name + = f.text_field :name, class: 'form-control' - .form-control{style: 'margin-top: 2%;'} - = f.label :email_template - = f.select 'email_template_id', options_from_collection_for_select(current_account.email_templates, 'id', 'subject') - or - = link_to 'create new template.', new_email_template_path, target: '_blank' + %label + Tag List + = select_tag :tags, options_for_select(@all_tags.map{ |t| [t, t] }), { include_blank: false, class: 'select2 form-control', multiple: true } - = hidden_field_tag 'q', params[:q] - = hidden_field_tag 'limit', params[:limit] - = hidden_field_tag 'query_from', (params[:query_from] || 'users') - = hidden_field_tag 'campaign_id', params[:campaign_id] + .form-control{style: 'margin-top: 2%;'} + = f.label :email_template + = f.select 'email_template_id', options_from_collection_for_select(current_account.email_templates, 'id', 'subject') + or + = link_to 'create new template.', new_email_template_path, target: '_blank' - .actions - = f.submit 'Save', class: 'btn btn-primary' - .col-md-12 - = link_to 'All Campaigns', campaigns_path, class: 'btn btn-default' + = hidden_field_tag 'q', params[:q] + = hidden_field_tag 'limit', params[:limit] + = hidden_field_tag 'query_from', (params[:query_from] || 'users') + = hidden_field_tag 'campaign_id', params[:campaign_id] + + .actions + = f.submit 'Save', class: 'btn btn-primary' \ No newline at end of file diff --git a/app/views/campaigns/show.html.haml b/app/views/campaigns/show.html.haml index 3c6c25a..a6e32e6 100644 --- a/app/views/campaigns/show.html.haml +++ b/app/views/campaigns/show.html.haml @@ -1,52 +1,66 @@ += page_title @campaign.name + +- content_for :page_title_right do + = form_tag send_emails_campaign_path(@campaign), method: :post, class: 'form-inline' do + %div.form-group + %label SMTP + = select_tag 'smtp_id', options_for_select(current_account.smtp_settings.map{|ss| [ ss.provider, ss.id ]}, current_account.smtp_settings.default_for_campaigns.try(:id)), include_blank: false, class: 'form-control' + = submit_tag 'Send', class: 'btn btn-success', data: { confirm: 'This email will send only to email addresses in draft status. Are you sure?' } + + .x_panel .x_title - %h3 - #{@campaign.name} - .clearfix - .col-md-4 - %p Campaign Tags: - %div{id: "CampaignTags-#{@campaign.id}"} - = render partial: 'tags/item_tags', locals: { item: @campaign } + %h4 Detail + .x_content + .row + .col-sm-4 + .panel.panel-default + .panel-heading + Tags + .panel-body + %div{id: "CampaignTags-#{@campaign.id}"} + = render partial: 'tags/item_tags', locals: { item: @campaign } + .col-sm-8 + .panel.panel-default + .panel-heading + Template + .panel-body + = render partial: 'email_templates/email_template', locals: { email_template: @campaign.email_template, user: @campaign.users.first } -= render 'template_form' .x_panel .x_title - %h3 Campaign Statistics - %small Add Sendgrid settings to get more detaily statistics. - = render 'stats' + %h4 Stats + .x_content + .row + .col-sm-8 + = render 'stats' + .col-sm-4 + = pie_chart @stats -.x_panel - = pie_chart @stats .x_panel .x_title - %h2 Filter Users - %ul.nav.navbar-right.panel_toolbox - %li - %a.collapse-link.pull-right - %i.fa.fa-chevron-up - .clearfix + %h4 Users + .title_right + .col-md-12.col-sm-12.col-xs-12.text-right + .x_content - %p Filter users to create new campaign from the existing campaign. = render partial: 'shared/advanced_search', locals: { form_url: "/campaigns/#{@campaign.id}" } - .col-sm-6 - = paginate @campaign_users - .clearfix + = link_to 'Create New Campaign For Filtered Users', new_campaign_path({ q: (params[:q].presence || 'all'), + limit: params[:limit_count], query_from: 'campaign', campaign_id: @campaign.id }), + class: 'btn btn-primary' + + %hr/ -.x_panel - = link_to 'Create New Campaign For Filtered Users', new_campaign_path({ q: (params[:q].presence || 'all'), - limit: params[:limit_count], query_from: 'campaign', campaign_id: @campaign.id }), - class: 'btn btn-success pull-right', style: 'margin-top: 1%' - .x_content %table.table.table-striped.projects %thead %tr %th Email %th Name %th Email Status - %th Tags + %th Campaing User Tags %tbody - @campaign_users.each do |camp_user| - if camp_user.user.present? @@ -57,3 +71,5 @@ %td %div{id: "CampaignUserTags-#{camp_user.id}"} = render partial: 'tags/item_tags', locals: { item: camp_user } + + = paginate @campaign_users \ No newline at end of file diff --git a/app/views/email_templates/_email_template.html.haml b/app/views/email_templates/_email_template.html.haml new file mode 100644 index 0000000..a38b100 --- /dev/null +++ b/app/views/email_templates/_email_template.html.haml @@ -0,0 +1,17 @@ +- body = Tilt::ERBTemplate.new { "#{email_template.body}" } +- subject = Tilt::ERBTemplate.new { "#{email_template.subject}" } + +%p + %strong Subject: + = subject.render(user).html_safe + +%p + %strong Body: + += body.render(User.first).html_safe + +%p + + += link_to 'Edit', edit_email_template_path(@campaign.email_template), class: 'btn btn-default' + diff --git a/app/views/email_templates/index.html.haml b/app/views/email_templates/index.html.haml index 126d849..3093c69 100644 --- a/app/views/email_templates/index.html.haml +++ b/app/views/email_templates/index.html.haml @@ -1,27 +1,35 @@ -%div - .page-title - .title_left - %h3 Listing Email Templates - .title_right - .col-md-12.col-sm-12.col-xs-12.text-right - = link_to new_email_template_path do - %button.btn.btn-primary New Email template -.clearfix += page_title "Email Templates" + +- content_for :page_title_right do + = link_to new_email_template_path do + %button.btn.btn-primary + %fa.fa.fa-plus + New Email Template + + .x_panel - %table.table.table-striped.projects - %thead - %tr - %th Subject - %th Campaigns - %th.text-center{width: '200px'} # - %tbody - - @email_templates.each do |template| + .x_title + %h4 Email Templates + .x_content + %table.table.table-striped.table-bordered.table-hover + %thead %tr - %td= template.subject - %td - - template.campaigns.each do |campaign| - = link_to campaign.name, campaign_path(campaign), class: 'btn btn-info btn-xs' + %th Subject + %th Campaigns + %th{width: '100'} # + %tbody + - @email_templates.each do |template| + %tr + %td= template.subject %td - = link_to 'Edit', edit_email_template_path(template), class: 'btn btn-sm btn-warning' - = link_to 'Show', template, class: 'btn btn-sm btn-default' - = link_to 'Destroy', template, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-sm btn-danger' + - template.campaigns.each do |campaign| + = link_to campaign.name, campaign_path(campaign), class: '' + , + + %td + = link_to edit_email_template_path(template), class: 'btn btn-sm btn-default btn-xs' do + %fa.fa.fa-pencil + = link_to template, class: 'btn btn-sm btn-default btn-xs' do + %fa.fa.fa-eye + = link_to template, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-sm btn-danger btn-xs' do + %fa.fa.fa-trash \ No newline at end of file diff --git a/app/views/email_templates/new.html.haml b/app/views/email_templates/new.html.haml index 2c314f2..12eee00 100644 --- a/app/views/email_templates/new.html.haml +++ b/app/views/email_templates/new.html.haml @@ -1,5 +1,7 @@ -%h1 New Email Template += page_title "New Email Template" -= render 'form' - -= link_to 'Back', email_templates_path +.x_panel + .x_title + %h4 New Email Template + .x_content + = render 'form' diff --git a/app/views/email_templates/show.html.haml b/app/views/email_templates/show.html.haml index f22d1b2..45923b0 100644 --- a/app/views/email_templates/show.html.haml +++ b/app/views/email_templates/show.html.haml @@ -1,13 +1,14 @@ - body = Tilt::ERBTemplate.new { "#{@email_template.body}" } - subject = Tilt::ERBTemplate.new { "#{@email_template.subject}" } += page_title subject.render(User.first).html_safe + +- content_for :page_title_right do + = link_to 'Edit', edit_email_template_path(@email_template), class: 'btn btn-default' + + .x_panel + .x_title + = subject.render(User.first).html_safe .panel-body - %h2.text-center= subject.render(User.first).html_safe = body.render(User.first).html_safe - -%hr/ - -= link_to 'Edit', edit_email_template_path(@email_template) -\| -= link_to 'Back', email_templates_path diff --git a/app/views/inbox/_detail.html.haml b/app/views/inbox/_detail.html.haml index b4e6fc9..07c04b4 100644 --- a/app/views/inbox/_detail.html.haml +++ b/app/views/inbox/_detail.html.haml @@ -1,27 +1,4 @@ .row - .col-sm-12 - .panel.panel-default - .panel-heading Reply Email - .panel-body - = form_tag reply_email_inbox_index_path, method: :post, remote: true, id: 'reply-form' do - .col-md-12 - = text_area_tag 'body', nil, rows: 5, placeholder: 'Write a reply... (recommended: HTML)', class: 'form-control' - = hidden_field_tag 'mail_to', @email - = hidden_field_tag 'subject', @subject - - .col-md-12 - .col-md-8 - .col-md-6 - Select an email template: - = select_tag 'reply_email_template', options_for_select(current_account.email_templates.map{|et| [ et.subject, et.body.html_safe ]}), onchange: 'reply_template_select()', include_blank: '- select -', class: 'form-control' - .col-md-6 - Select SMTP Settings - = select_tag 'smtp_id', options_for_select(current_account.smtp_settings.map{|ss| [ ss.provider, ss.id ]}, current_account.smtp_settings.default_for_reply.try(:id)), include_blank: false, class: 'form-control' - .col-md-4.text-right - = submit_tag 'Send Message', id: 'reply-submit', class: 'btn btn-success', style: 'margin-top: 8%;' - .col-md-12 - #message-status.text-center.text-success - .col-sm-12 - if user.present? .panel.panel-default @@ -51,26 +28,33 @@ = render partial: 'tags/item_tags', locals: { item: campaign_user } - if campaign_users.count < 1 %p.text-center.text-danger Campaign User Not Found! - - if user.user_attributes.present? - .row - .panel.panel-default - .panel-heading - User Attributes - .panel-body - %table.table-bordered.table-condensed - %thead - %tr - %td Attribute - %td Value - %tbody - - user.user_attributes.each do |attr| - %tr - %td= attr.key - %td - - if attr.value.include?('http') - = link_to attr.value, attr.value, target: '_blank' - - else - = attr.value + + = render partial: 'user_attributes/index', locals: { user: user } + +.row + .col-sm-12 + .panel.panel-default + .panel-heading Reply Email + .panel-body + = form_tag reply_email_inbox_index_path, method: :post, remote: true, id: 'reply-form' do + .col-md-12 + = text_area_tag 'body', nil, rows: 5, placeholder: 'Write a reply... (recommended: HTML)', class: 'form-control' + = hidden_field_tag 'mail_to', @email + = hidden_field_tag 'subject', @subject + + .col-md-12 + .col-md-8 + .col-md-6 + Select an email template: + = select_tag 'reply_email_template', options_for_select(current_account.email_templates.map{|et| [ et.subject, et.body.html_safe ]}), onchange: 'reply_template_select()', include_blank: '- select -', class: 'form-control' + .col-md-6 + Select SMTP Settings + = select_tag 'smtp_id', options_for_select(current_account.smtp_settings.map{|ss| [ ss.provider, ss.id ]}, current_account.smtp_settings.default_for_reply.try(:id)), include_blank: false, class: 'form-control' + .col-md-4.text-right + = submit_tag 'Send Message', id: 'reply-submit', class: 'btn btn-success', style: 'margin-top: 8%;' + .col-md-12 + #message-status.text-center.text-success + .row .col-sm-12 .panel.panel-default diff --git a/app/views/inbox/detail.js.erb b/app/views/inbox/detail.js.erb index 609379b..e91598d 100644 --- a/app/views/inbox/detail.js.erb +++ b/app/views/inbox/detail.js.erb @@ -1,2 +1,4 @@ $("#email-detail").html("<%= escape_javascript render(partial: 'inbox/detail', locals: { user: @user, campaign_users: @campaign_users, message: @message, subject: @subject, email: @email, has_attach: @has_attach }) %>"); -$(window).scrollTop(0); \ No newline at end of file +$(window).scrollTop(0); + +jQuery.ready(); \ No newline at end of file diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 8584efe..afbf6b5 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -104,12 +104,20 @@ /Page Content .right_col{:role => "main"} - %div - .col-md-12 - - if flash.now[:notice] + - if flash.now[:notice] + .row + .col-md-12 .alert.alert-info %p#notice= flash.now[:notice] - = yield + + .page-title + .title_left + %h1= yield :page_title + .title_right + .col-md-12.col-sm-12.col-xs-12.text-right + = yield :page_title_right + + = yield - else %body.login diff --git a/app/views/shared/_advanced_search.html.haml b/app/views/shared/_advanced_search.html.haml index 1b4466e..fb15a14 100644 --- a/app/views/shared/_advanced_search.html.haml +++ b/app/views/shared/_advanced_search.html.haml @@ -15,4 +15,5 @@ = s.sort_select .actions - = f.submit "Search", class: 'btn btn-primary' + = f.submit "Search", class: 'btn btn-default' + = yield :extra_buttons_in_search \ No newline at end of file diff --git a/app/views/tags/_item_tags.html.haml b/app/views/tags/_item_tags.html.haml index 7a6eaf8..71cae8d 100644 --- a/app/views/tags/_item_tags.html.haml +++ b/app/views/tags/_item_tags.html.haml @@ -1,12 +1,14 @@ .row - - item.tags.each do |tag| - = link_to remove_tag_from_item_tags_path(item_id: item.id, item_type: item.class.name, name: tag.name), method: :post, remote: true, data: { confirm: 'Are you sure?' }, class: 'btn btn-info btn-xs' do - = tag - %span.fa.fa-trash + .col-sm-12 + - item.tags.each do |tag| + = link_to remove_tag_from_item_tags_path(item_id: item.id, item_type: item.class.name, name: tag.name), method: :post, remote: true, data: { confirm: 'Are you sure?' }, class: 'btn btn-info btn-xs' do + = tag + %span.fa.fa-trash .row - = form_tag(add_tag_to_item_tags_path, remote: true) do - -#= text_field_tag :name, nil, placeholder: "Type tag for #{item.class.name} and press Enter", class: 'form-control', style: 'height: 25px;width: 95%;' - = hidden_field_tag :item_type, item.class.name - = hidden_field_tag :item_id, item.id - = hidden_field_tag :authenticity_token, form_authenticity_token - = select_tag 'name', '', { class: 'tag-select form-control', style: 'height: 25px;width: 95%;', multiple: true, include_blank: true, onchange: "$(this).submit();", placeholder: "Type tag for #{item.class.name} and press Enter" } + .col-sm-12 + = form_tag(add_tag_to_item_tags_path, remote: true) do + -#= text_field_tag :name, nil, placeholder: "Type tag for #{item.class.name} and press Enter", class: 'form-control', style: 'height: 25px;width: 95%;' + = hidden_field_tag :item_type, item.class.name + = hidden_field_tag :item_id, item.id + = hidden_field_tag :authenticity_token, form_authenticity_token + = select_tag 'name', '', { class: 'tag-select form-control', style: 'height: 25px;width: 95%;', multiple: true, include_blank: true, onchange: "$(this).submit();", placeholder: "Type tag for #{item.class.name} and press Enter" } diff --git a/app/views/user_attributes/_attribute_row.html.haml b/app/views/user_attributes/_attribute_row.html.haml new file mode 100644 index 0000000..64829f8 --- /dev/null +++ b/app/views/user_attributes/_attribute_row.html.haml @@ -0,0 +1,6 @@ +%tr{id: "attr-#{attr.id}"} + %td= editable attr, :key, url: user_user_attribute_path(user, attr), value: attr.key + %td= editable attr, :value, url: user_user_attribute_path(user, attr), value: attr.value + %td{width: "30"} + = link_to user_user_attribute_path(user, attr), method: :delete, remote: true, data: { confirm: 'Are you sure?' }, class: '' do + %span.fa.fa-trash \ No newline at end of file diff --git a/app/views/user_attributes/_attributes_table.html.haml b/app/views/user_attributes/_attributes_table.html.haml index a1886ea..b0b93ad 100644 --- a/app/views/user_attributes/_attributes_table.html.haml +++ b/app/views/user_attributes/_attributes_table.html.haml @@ -1,21 +1,12 @@ -- if user.user_attributes.count > 0 - .row - .col-md-12 - .x_panel - .x_content - %table.table.table-striped.projects - %thead - %tr - %th Key - %th Value - %th # - %tbody - - user.user_attributes.each do |attr| - - if attr.id - %tr{id: "attr-#{attr.id}"} - %td= editable attr, :key, url: user_user_attribute_path(user, attr), value: attr.key - %td= editable attr, :value, url: user_user_attribute_path(user, attr), value: attr.value - %td - = link_to user_user_attribute_path(user, attr), method: :delete, remote: true, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger btn-xs' do - Remove - %span.fa.fa-trash +.row + .col-md-12 + %table.table.table-condensed.table-bordered + %thead + %tr + %th{width: "50%"} Key + %th{width: "50%"} Value + %th # + %tbody + = render partial: 'user_attributes/form', locals: { user: user } + - user.user_attributes.each do |attr| + = render partial: 'user_attributes/attribute_row', locals: { attr: attr, user: user } diff --git a/app/views/user_attributes/_form.html.haml b/app/views/user_attributes/_form.html.haml new file mode 100644 index 0000000..c95ef8d --- /dev/null +++ b/app/views/user_attributes/_form.html.haml @@ -0,0 +1,9 @@ += form_for [user, UserAttribute.new], remote: true do |f| + %tr + %td + = f.text_field :key, class: 'form-control' + %td + = f.text_field :value, class: 'form-control' + %td + .hide + = f.submit 'Save', class: 'btn btn-primary btn-xs' \ No newline at end of file diff --git a/app/views/user_attributes/_index.html.haml b/app/views/user_attributes/_index.html.haml new file mode 100644 index 0000000..aff9801 --- /dev/null +++ b/app/views/user_attributes/_index.html.haml @@ -0,0 +1,2 @@ +%div{id: "attrTable-#{user.id}"} + = render partial: 'user_attributes/attributes_table', locals: { user: user } \ No newline at end of file diff --git a/app/views/user_attributes/create.js.erb b/app/views/user_attributes/create.js.erb index dde87be..499eb9d 100644 --- a/app/views/user_attributes/create.js.erb +++ b/app/views/user_attributes/create.js.erb @@ -1,2 +1,2 @@ -$("#attrTable").html("<%= escape_javascript render(partial: 'user_attributes/attributes_table', locals: { user: @user }) %>"); +$("#<%= "attrTable-#{@user.id}" %> table tbody").append("<%= escape_javascript render(partial: 'user_attributes/attribute_row', locals: { attr: @attribute, user: @user }) %>").effect('highlight', {}, 3000); $("#new_user_attribute")[0].reset(); \ No newline at end of file diff --git a/app/views/user_attributes/index.html.haml b/app/views/user_attributes/index.html.haml index 3766f7f..3823fe4 100644 --- a/app/views/user_attributes/index.html.haml +++ b/app/views/user_attributes/index.html.haml @@ -6,19 +6,9 @@ .row .col-md-12 .x_panel - = form_for [@user, @user.user_attributes.new], remote: true do |f| - .col-sm-5 - = f.label :key - = f.text_field :key, class: 'form-control' - .col-sm-5 - = f.label :value - = f.text_field :value, class: 'form-control' - .col-sm-2 - .actions{style: 'margin-top: 23px;'} - = f.submit 'Save', class: 'btn btn-primary' -#attrTable - = render partial: 'user_attributes/attributes_table', locals: { user: @user } + += render partial: 'user_attributes/attributes_table', locals: { user: @user } .page-title .title_left diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml index 9f8df2f..5244b0b 100644 --- a/app/views/users/index.html.haml +++ b/app/views/users/index.html.haml @@ -1,94 +1,88 @@ -%div - .page-title - .title_left - %h3 Listing Users - .title_right - .col-md-12.col-sm-12.col-xs-12.text-right - = link_to new_user_path do - %button.btn.btn-primary Add a User - = link_to import_users_path do - %button.btn.btn-success Import Users - - .clearfix - .row - .col-md-12 - .x_panel - .x_title - %h2 Filter Users - %ul.nav.navbar-right.panel_toolbox - %li - %a.collapse-link.pull-right - %i.fa.fa-chevron-up - .clearfix - .x_content - %p Filter users to create new campaign or add to existing campaign. - / start project list - = render partial: 'shared/advanced_search', locals: { form_url: nil } - - .row - .col-md-12 - .x_panel - .x_title - %h2 Filtered Users - %p.label.label-primary{style: 'margin-left: 1%;'} - = @total_user_count - - - if @total_user_count > 0 - .title_right - .col-md-12.col-sm-12.col-xs-12.text-right - .pull-right - = link_to new_campaign_path({ q: (params[:q].presence || 'all'), limit: params[:limit_count] }), class: 'btn btn-success' do - %i.fa.fa-plus - Create New Campaign - - if current_account.campaigns.present? - .pull-right - = form_tag add_users_campaigns_path, method: :post do - = select_tag 'campaign_id', options_for_select(current_account.campaigns.map{ |c| [c.name, c.id] }, nil), class: 'form-control', style: 'width: 28%; display: inline' - = hidden_field_tag 'filter', (params[:q].presence || {}).to_json - = hidden_field_tag 'limit', params[:limit_count] - = button_tag class: 'btn btn-primary btn-mid', type: :submit do - %i.fa.fa-arrow-circle-right - Add to selected campaign - %span or   - .clearfix - .x_content - %table.table.table-striped.projects - %thead - %tr - %th Email - %th Name - %th Tags - %th Campaigns - %th Attributes - %th.text-center # - %tbody - - @users.each do |user| - %tr{id: "user-#{user.id}"} - %td= user.email - %td= user.name - %td - %div{id: "UserTags-#{user.id}"} - = render partial: 'tags/item_tags', locals: { item: user } - - %td - - user.campaigns.each do |cp| - = link_to "##{cp.id},", campaign_path(cp), 'data-toggle': 'tooltip', 'data-placement': 'top', 'data-original-title': "#{cp.name}" - %td - - user.user_attributes.each do |attr| - = "#{attr.key}: #{attr.value}" - %br/ - %td - = link_to user_path(user), class: 'btn btn-danger btn-xs', method: :delete, remote: true, data: { confirm: 'Are you sure?' } do - %i.fa.fa-trash-o - Delete - = link_to user_user_attributes_path(user), class: 'btn btn-warning btn-xs' do - %i.fa.fa-eye - Show - - = paginate @users - = link_to (request.fullpath + '?&format=csv'), class: 'btn btn-dark pull-right' do - %i.fa.fa-external-link - Export to CSV - = link_to (request.fullpath + '?&format=xlsx'), class: 'btn btn-dark pull-right' do - %i.fa.fa-external-link - Export to Excel \ No newline at end of file += content_for :extra_buttons_in_search do + = link_to (request.fullpath + '?&format=csv'), class: 'btn btn-default' do + %i.fa.fa-external-link + Export to CSV + = link_to (request.fullpath + '?&format=xlsx'), class: 'btn btn-default' do + %i.fa.fa-external-link + Export to Excel + + += page_title 'Users' + + += content_for :page_title_right do + = link_to new_user_path do + %button.btn.btn-primary + %span.fa.fa-plus + New User + +.clearfix + +.row + .col-md-12 + .x_panel + .x_title + %h4 Users + .x_content + + = render partial: 'shared/advanced_search', locals: { form_url: nil } + + - if params[:q].present? + .pull-left + = link_to new_campaign_path({ q: (params[:q].presence || 'all'), limit: params[:limit_count] }), class: 'btn btn-primary' do + %i.fa.fa-plus + = "Create new campaign for" + %span.label.label-success= @total_user_count + = "users" + + - if current_account.campaigns.count > 0 + OR +   + + - if current_account.campaigns.count > 0 + = form_tag add_users_campaigns_path, method: :post, class: 'form-inline' do + + .form-group + = hidden_field_tag 'filter', (params[:q].presence || {}).to_json + = hidden_field_tag 'limit', params[:limit_count] + = select_tag 'campaign_id', options_for_select(current_account.campaigns.map{ |c| [c.name, c.id] }, nil), class: 'form-control' + + = button_tag class: 'btn btn-primary btn-mid', type: :submit do + %i.fa.fa-arrow-circle-right + = "Add" + %span.label.label-success= @total_user_count + = "users to selected campaign" + + = paginate @users + + %table.table.table-striped.table-bordered.table-hover + %thead + %tr + %th{width: "200"} Email + %th{width: "200"} Tags + %th Name + %th Campaigns + %th Attributes + %th{width: "100"} + %tbody + - @users.each do |user| + %tr{id: "user-#{user.id}"} + %td= user.email + %td + %div{id: "UserTags-#{user.id}"} + = render partial: 'tags/item_tags', locals: { item: user } + %td= user.name + + %td + - user.campaigns.each do |cp| + = link_to "##{cp.id},", campaign_path(cp), 'data-toggle': 'tooltip', 'data-placement': 'top', 'data-original-title': "#{cp.name}" + %td + = render partial: 'user_attributes/index', locals: { user: user } + %td + = link_to user_path(user), class: 'btn btn-danger btn-xs', method: :delete, remote: true, data: { confirm: 'Are you sure?' } do + %i.fa.fa-trash-o + + = link_to user_path(user), class: 'btn btn-default btn-xs' do + %i.fa.fa-eye + + = paginate @users \ No newline at end of file diff --git a/app/views/users/new.html.haml b/app/views/users/new.html.haml index 80a1056..04f639c 100644 --- a/app/views/users/new.html.haml +++ b/app/views/users/new.html.haml @@ -1,17 +1,23 @@ -.x_panel - %h4 Add a user - = form_tag create_single_users_path, id: 'single-user', method: :post do +.row + .col-sm-8 + .x_panel + .x_title + %h4 New User - = label_tag 'Name (optional)' - = text_field_tag :name, nil, { class: 'form-control' } + = form_tag create_single_users_path, id: 'single-user', method: :post do - = label_tag 'Email' - = email_field_tag :email, nil, { class: 'form-control', required: true } + = label_tag 'Name (optional)' + = text_field_tag :name, nil, { class: 'form-control' } - = label_tag 'Tags' - = select_tag :tags, options_for_select(@all_tags.map{ |t| [t, t] }), { include_blank: false, class: 'select2', multiple: true } - .actions - .col-md-6 - = submit_tag 'Add User', class: 'btn btn-primary' - .col-md-6.text-right - = link_to 'Import Users From a File', import_users_path, class: 'btn btn-default' + = label_tag 'Email' + = email_field_tag :email, nil, { class: 'form-control', required: true } + + = label_tag 'Tags' + = select_tag :tags, options_for_select(@all_tags.map{ |t| [t, t] }), { include_blank: false, class: 'select2', multiple: true } + .actions + .pull-right + = submit_tag 'Save', class: 'btn btn-primary' + + .col-sm-4 + = link_to 'Import Users From CSV or XLS files', import_users_path, class: 'btn btn-default' + = link_to 'Create Users Over API', '#', class: 'btn btn-default' diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml new file mode 100644 index 0000000..ad46b72 --- /dev/null +++ b/app/views/users/show.html.haml @@ -0,0 +1,20 @@ +.page-title + .title_left + %h1= @user.email + +.clearfix + +.row + .col-sm-6 + .x_panel + .x_title + %h3 Attributes + .x_content + = render partial: 'user_attributes/index', locals: { user: @user } + + .col-sm-6 + .x_panel + .x_title + %h3 Campaigns + .x_content + = render partial: 'campaign_users/index', locals: { user: @user } diff --git a/config/routes.rb b/config/routes.rb index 9254f95..186c08b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,7 +11,7 @@ root to: 'home#index' - resources :users, only: [:index, :destroy, :new, :create] do + resources :users do collection do post 'create_single' get 'import' From 26e5176778dd3161c5babcf8ec53a1f3b33cdf6f Mon Sep 17 00:00:00 2001 From: Muhammet Date: Mon, 17 Jul 2017 23:44:09 -0700 Subject: [PATCH 02/13] upgrade ruby version --- .ruby-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ruby-version b/.ruby-version index 276cbf9..0bee604 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.3.0 +2.3.3 From c53e5e9e88cc86d3f124a84741d41a709213e052 Mon Sep 17 00:00:00 2001 From: Sadik Ay Date: Tue, 18 Jul 2017 14:03:47 +0300 Subject: [PATCH 03/13] add account scope to notes --- app/controllers/notes_controller.rb | 8 ++++---- app/views/notes/show.html.haml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index a72a3e1..bc93890 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -3,7 +3,7 @@ class NotesController < ApplicationController # GET /notes def index - @notes = Note.all + @notes = current_account.notes.all end # GET /notes/1 @@ -12,7 +12,7 @@ def show # GET /notes/new def new - @note = Note.new + @note = current_account.notes.new end # GET /notes/1/edit @@ -21,7 +21,7 @@ def edit # POST /notes def create - @note = Note.new(note_params) + @note = current_account.notes.new(note_params) respond_to do |format| if @note.save @@ -54,7 +54,7 @@ def destroy private # Use callbacks to share common setup or constraints between actions. def set_note - @note = Note.find(params[:id]) + @note = current_account.notes.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. diff --git a/app/views/notes/show.html.haml b/app/views/notes/show.html.haml index 7f11098..90366af 100644 --- a/app/views/notes/show.html.haml +++ b/app/views/notes/show.html.haml @@ -3,7 +3,7 @@ %h2.text-center= @note.title = @note.content.try (:html_safe) -%hr/ - = link_to 'Edit', edit_note_path(@note) +\- += link_to 'Back', notes_path From 4b588d25583255ab2f6e0e66d94a70e4da9319ee Mon Sep 17 00:00:00 2001 From: Muhammet Date: Tue, 18 Jul 2017 11:20:29 -0700 Subject: [PATCH 04/13] detailed user list --- app/controllers/users_controller.rb | 31 +++++++-- app/views/layouts/application.html.haml | 8 ++- app/views/notes/show.html.haml | 15 +++-- .../users/_create_campaign_buttons.html.haml | 25 +++++++ app/views/users/detailed_list.html.haml | 66 +++++++++++++++++++ app/views/users/index.html.haml | 29 +------- app/views/users/index.xls.erb | 7 +- config/routes.rb | 1 + 8 files changed, 133 insertions(+), 49 deletions(-) create mode 100644 app/views/users/_create_campaign_buttons.html.haml create mode 100644 app/views/users/detailed_list.html.haml diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 996b36c..2ec11ea 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,14 +2,16 @@ class UsersController < ApplicationController before_action :set_all_tags, only: [:new, :import] def index - @q = current_account.users.includes(:user_attributes, :campaigns, :campaign_users, :tags) - .ransack(params[:q]) - @q.build_grouping unless @q.groupings.any? - @q.sorts = 'created_at DESC' if @q.sorts.empty? + users_list + respond_to do |format| + format.html + format.xlsx { render xlsx: 'download', filename: "Users-#{Time.now.strftime("%Y%m%d%H%M")}.xlsx", locals: { users: users_to_export } } + format.csv { send_data users_to_export.to_csv_file, filename: "Users-#{Time.now.strftime("%Y%m%d%H%M")}.csv" } + end + end - @users = ransack_results_with_limit - @associations = [:tags, :user_attributes, :campaign_users, :campaign_users_tags, :campaigns, :campaigns_tags] - @total_user_count = @users.total_count + def detailed_list + users_list respond_to do |format| format.html @@ -62,4 +64,19 @@ def destroy format.js end end + + private + + def users_list + @q = current_account.users.includes(:user_attributes, :campaigns, :campaign_users, :tags) + .ransack(params[:q]) + @q.build_grouping unless @q.groupings.any? + @q.sorts = 'created_at DESC' if @q.sorts.empty? + + @users = ransack_results_with_limit + @associations = [:tags, :user_attributes, :campaign_users, :campaign_users_tags, :campaigns, :campaigns_tags] + @total_user_count = @users.total_count + + @user_attribute_keys = UserAttribute.joins(:user).where('users.account_id = ?', current_account.id).select('DISTINCT key').order('key ASC').map(&:key) + end end diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index afbf6b5..2d99642 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -36,11 +36,13 @@ %span.fa.fa-chevron-down %ul.nav.child_menu %li - %a{:href => users_path } List Users + %a{:href => users_path } List %li - %a{:href => new_user_path } Add a User + %a{:href => detailed_list_users_path } Detailed List %li - %a{:href => import_users_path} Import Users List + %a{:href => new_user_path } Add + %li + %a{:href => import_users_path} Import %li %a{:href => inbox_index_path} diff --git a/app/views/notes/show.html.haml b/app/views/notes/show.html.haml index 90366af..682dc3d 100644 --- a/app/views/notes/show.html.haml +++ b/app/views/notes/show.html.haml @@ -1,9 +1,10 @@ -.x_panel - .panel-body - %h2.text-center= @note.title - = @note.content.try (:html_safe) += page_title @note.title -= link_to 'Edit', edit_note_path(@note) -\- -= link_to 'Back', notes_path +- content_for :page_title_right do + = link_to 'Edit', edit_note_path(@note), class: 'btn btn-default' +.x_panel + .x_title + %h4= @note.title + .panel-body + = @note.content.try (:html_safe) \ No newline at end of file diff --git a/app/views/users/_create_campaign_buttons.html.haml b/app/views/users/_create_campaign_buttons.html.haml new file mode 100644 index 0000000..47e6a54 --- /dev/null +++ b/app/views/users/_create_campaign_buttons.html.haml @@ -0,0 +1,25 @@ +- if params[:q].present? + .pull-left + = link_to new_campaign_path({ q: (params[:q].presence || 'all'), limit: params[:limit_count] }), class: 'btn btn-primary' do + %i.fa.fa-plus + = "Create new campaign for" + %span.label.label-success= @total_user_count + = "users" + + - if current_account.campaigns.count > 0 + OR +   + + - if current_account.campaigns.count > 0 + = form_tag add_users_campaigns_path, method: :post, class: 'form-inline' do + + .form-group + = hidden_field_tag 'filter', (params[:q].presence || {}).to_json + = hidden_field_tag 'limit', params[:limit_count] + = select_tag 'campaign_id', options_for_select(current_account.campaigns.map{ |c| [c.name, c.id] }, nil), class: 'form-control' + + = button_tag class: 'btn btn-primary btn-mid', type: :submit do + %i.fa.fa-arrow-circle-right + = "Add" + %span.label.label-success= @total_user_count + = "users to selected campaign" diff --git a/app/views/users/detailed_list.html.haml b/app/views/users/detailed_list.html.haml new file mode 100644 index 0000000..ef868db --- /dev/null +++ b/app/views/users/detailed_list.html.haml @@ -0,0 +1,66 @@ += content_for :extra_buttons_in_search do + = link_to (request.fullpath + '?&format=csv'), class: 'btn btn-default' do + %i.fa.fa-external-link + Export to CSV + = link_to (request.fullpath + '?&format=xlsx'), class: 'btn btn-default' do + %i.fa.fa-external-link + Export to Excel + + += page_title 'Detailed Users' + + += content_for :page_title_right do + = link_to new_user_path do + %button.btn.btn-primary + %span.fa.fa-plus + New User + +.clearfix + +.row + .col-md-12 + .x_panel + .x_title + %h4 Detailed Users + .x_content + + = render partial: 'shared/advanced_search', locals: { form_url: detailed_list_users_path } + + = render 'create_campaign_buttons' + + = paginate @users + + %table.table.table-striped.table-bordered.table-hover + %thead + %tr + %th{width: "200"} Email + %th{width: "200"} Tags + %th Name + %th Campaigns + - @user_attribute_keys.each do |key| + %th= key + %th{width: "100"} + %tbody + - @users.each do |user| + %tr{id: "user-#{user.id}"} + %td= user.email + %td + %div{id: "UserTags-#{user.id}"} + = render partial: 'tags/item_tags', locals: { item: user } + %td= user.name + + %td + - user.campaigns.each do |cp| + = link_to "##{cp.id},", campaign_path(cp), 'data-toggle': 'tooltip', 'data-placement': 'top', 'data-original-title': "#{cp.name}" + - @user_attribute_keys.each do |key| + %td= user.user_attributes.to_a.select{ |ua| ua.key == key }.first.try(:value) + + %td + = link_to user_path(user), class: 'btn btn-danger btn-xs', method: :delete, remote: true, data: { confirm: 'Are you sure?' } do + %i.fa.fa-trash-o + + = link_to user_path(user), class: 'btn btn-default btn-xs' do + %i.fa.fa-eye + + = paginate @users \ No newline at end of file diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml index 5244b0b..458f644 100644 --- a/app/views/users/index.html.haml +++ b/app/views/users/index.html.haml @@ -16,8 +16,6 @@ %span.fa.fa-plus New User -.clearfix - .row .col-md-12 .x_panel @@ -27,31 +25,7 @@ = render partial: 'shared/advanced_search', locals: { form_url: nil } - - if params[:q].present? - .pull-left - = link_to new_campaign_path({ q: (params[:q].presence || 'all'), limit: params[:limit_count] }), class: 'btn btn-primary' do - %i.fa.fa-plus - = "Create new campaign for" - %span.label.label-success= @total_user_count - = "users" - - - if current_account.campaigns.count > 0 - OR -   - - - if current_account.campaigns.count > 0 - = form_tag add_users_campaigns_path, method: :post, class: 'form-inline' do - - .form-group - = hidden_field_tag 'filter', (params[:q].presence || {}).to_json - = hidden_field_tag 'limit', params[:limit_count] - = select_tag 'campaign_id', options_for_select(current_account.campaigns.map{ |c| [c.name, c.id] }, nil), class: 'form-control' - - = button_tag class: 'btn btn-primary btn-mid', type: :submit do - %i.fa.fa-arrow-circle-right - = "Add" - %span.label.label-success= @total_user_count - = "users to selected campaign" + = render 'create_campaign_buttons' = paginate @users @@ -81,7 +55,6 @@ %td = link_to user_path(user), class: 'btn btn-danger btn-xs', method: :delete, remote: true, data: { confirm: 'Are you sure?' } do %i.fa.fa-trash-o - = link_to user_path(user), class: 'btn btn-default btn-xs' do %i.fa.fa-eye diff --git a/app/views/users/index.xls.erb b/app/views/users/index.xls.erb index 3ce4ded..95e2f4d 100644 --- a/app/views/users/index.xls.erb +++ b/app/views/users/index.xls.erb @@ -1,4 +1,3 @@ -<% other_attributes = UserAttribute.where(user_id: @users.pluck(:id)).pluck(:key).uniq %> Name Email - <% other_attributes.each do |atr| %> + <% @user_attribute_keys.each do |atr| %> <%= atr %> <% end %> Price @@ -19,8 +18,8 @@ <%= user.name %> <%= user.email %> - <% other_attributes.each do |atr| %> - <%= user.user_attributes.find_by(key: atr).try(:value) %> + <% @user_attribute_keys.each do |key| %> + <%= user.user_attributes.select{ |ua| ua.key == key }.first.try(:value) %> <% end %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index 186c08b..e81eed2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -15,6 +15,7 @@ collection do post 'create_single' get 'import' + get 'detailed_list' end resources :user_attributes From e58a6ba00ad28bb78bbd76fcdaa0eb856bafc4e5 Mon Sep 17 00:00:00 2001 From: Muhammet Date: Tue, 18 Jul 2017 11:27:16 -0700 Subject: [PATCH 05/13] clean --- app/controllers/users_controller.rb | 35 ++++++++++------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2ec11ea..1a43f55 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,7 +2,17 @@ class UsersController < ApplicationController before_action :set_all_tags, only: [:new, :import] def index - users_list + @q = current_account.users.includes(:user_attributes, :campaigns, :campaign_users, :tags) + .ransack(params[:q]) + @q.build_grouping unless @q.groupings.any? + @q.sorts = 'created_at DESC' if @q.sorts.empty? + + @users = ransack_results_with_limit + @associations = [:tags, :user_attributes, :campaign_users, :campaign_users_tags, :campaigns, :campaigns_tags] + @total_user_count = @users.total_count + + @user_attribute_keys = UserAttribute.joins(:user).where('users.account_id = ?', current_account.id).select('DISTINCT key').order('key ASC').map(&:key) + respond_to do |format| format.html format.xlsx { render xlsx: 'download', filename: "Users-#{Time.now.strftime("%Y%m%d%H%M")}.xlsx", locals: { users: users_to_export } } @@ -11,13 +21,7 @@ def index end def detailed_list - users_list - - respond_to do |format| - format.html - format.xlsx { render xlsx: 'download', filename: "Users-#{Time.now.strftime("%Y%m%d%H%M")}.xlsx", locals: { users: users_to_export } } - format.csv { send_data users_to_export.to_csv_file, filename: "Users-#{Time.now.strftime("%Y%m%d%H%M")}.csv" } - end + index end def new; end @@ -64,19 +68,4 @@ def destroy format.js end end - - private - - def users_list - @q = current_account.users.includes(:user_attributes, :campaigns, :campaign_users, :tags) - .ransack(params[:q]) - @q.build_grouping unless @q.groupings.any? - @q.sorts = 'created_at DESC' if @q.sorts.empty? - - @users = ransack_results_with_limit - @associations = [:tags, :user_attributes, :campaign_users, :campaign_users_tags, :campaigns, :campaigns_tags] - @total_user_count = @users.total_count - - @user_attribute_keys = UserAttribute.joins(:user).where('users.account_id = ?', current_account.id).select('DISTINCT key').order('key ASC').map(&:key) - end end From 9e089e5042b6dd8eb67ba1d10e1c1c70dde24a17 Mon Sep 17 00:00:00 2001 From: Sadik Ay Date: Wed, 19 Jul 2017 12:12:07 +0300 Subject: [PATCH 06/13] fixes attribute update from inbox --- app/controllers/user_attributes_controller.rb | 2 -- app/views/inbox/_detail.html.haml | 8 +++++--- app/views/user_attributes/index.html.haml | 20 ------------------- app/views/users/detailed_list.html.haml | 2 +- 4 files changed, 6 insertions(+), 26 deletions(-) delete mode 100644 app/views/user_attributes/index.html.haml diff --git a/app/controllers/user_attributes_controller.rb b/app/controllers/user_attributes_controller.rb index 1f80794..ba0416e 100644 --- a/app/controllers/user_attributes_controller.rb +++ b/app/controllers/user_attributes_controller.rb @@ -2,8 +2,6 @@ class UserAttributesController < ApplicationController helper_method :xeditable? before_action :set_user - def index; end - def create @attribute = @user.user_attributes.create(attribute_params) end diff --git a/app/views/inbox/_detail.html.haml b/app/views/inbox/_detail.html.haml index 07c04b4..d98a8a9 100644 --- a/app/views/inbox/_detail.html.haml +++ b/app/views/inbox/_detail.html.haml @@ -11,7 +11,7 @@ .col-lg-6 .panel.panel-default .panel-heading - = link_to (user.name || user.email), user_user_attributes_path(user), target: '_blank' + = link_to (user.name || user.email), user_path(user), target: '_blank' .panel-body %div{id: "UserTags-#{user.id}"} = render partial: 'tags/item_tags', locals: { item: user } @@ -28,8 +28,10 @@ = render partial: 'tags/item_tags', locals: { item: campaign_user } - if campaign_users.count < 1 %p.text-center.text-danger Campaign User Not Found! - - = render partial: 'user_attributes/index', locals: { user: user } + .row + .clearfix + = form_for [user, UserAttribute.new], remote: true do |f| + = render partial: 'user_attributes/index', locals: { user: user } .row .col-sm-12 diff --git a/app/views/user_attributes/index.html.haml b/app/views/user_attributes/index.html.haml deleted file mode 100644 index 3823fe4..0000000 --- a/app/views/user_attributes/index.html.haml +++ /dev/null @@ -1,20 +0,0 @@ -.page-title - .title_left - %h3 - User Attributes For: - = @user.name || @user.email -.row - .col-md-12 - .x_panel - - -= render partial: 'user_attributes/attributes_table', locals: { user: @user } - -.page-title - .title_left - %h3 - User Tags: -.x_panel - .col-sm-5 - %div{id: "UserTags-#{@user.id}"} - = render partial: 'tags/item_tags', locals: { item: @user } \ No newline at end of file diff --git a/app/views/users/detailed_list.html.haml b/app/views/users/detailed_list.html.haml index ef868db..5e37568 100644 --- a/app/views/users/detailed_list.html.haml +++ b/app/views/users/detailed_list.html.haml @@ -31,7 +31,7 @@ = paginate @users - %table.table.table-striped.table-bordered.table-hover + %table.table.table-striped.table-bordered.table-hover{style: 'background-color: white;'} %thead %tr %th{width: "200"} Email From b97f40a8eda64780f60ac4f73327f9d398395df6 Mon Sep 17 00:00:00 2001 From: Sadik Ay Date: Wed, 19 Jul 2017 16:43:30 +0300 Subject: [PATCH 07/13] add creating user via api --- app/controllers/api/v1/api_base_controller.rb | 12 +++++++ app/controllers/api/v1/users_controller.rb | 33 +++++++++++++++++++ app/models/account.rb | 7 ++++ config/routes.rb | 5 +++ ...303_add_authentication_token_to_account.rb | 6 ++++ 5 files changed, 63 insertions(+) create mode 100644 app/controllers/api/v1/api_base_controller.rb create mode 100644 app/controllers/api/v1/users_controller.rb create mode 100644 db/migrate/20170719120303_add_authentication_token_to_account.rb diff --git a/app/controllers/api/v1/api_base_controller.rb b/app/controllers/api/v1/api_base_controller.rb new file mode 100644 index 0000000..8a774d1 --- /dev/null +++ b/app/controllers/api/v1/api_base_controller.rb @@ -0,0 +1,12 @@ +class Api::V1::ApiBaseController < ActionController::API + include ActionController::HttpAuthentication::Token::ControllerMethods + + before_filter :authenticate + + protected + def authenticate + authenticate_or_request_with_http_token do |token, _options| + @api_account = Account.find_by(authentication_token: token) + end + end +end diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb new file mode 100644 index 0000000..39b002d --- /dev/null +++ b/app/controllers/api/v1/users_controller.rb @@ -0,0 +1,33 @@ +class Api::V1::UsersController < Api::V1::ApiBaseController + # Creates User. + # Create a user for authenticated account. + # == Example Request + # curl -i -H "Authorization: Token token=7LGWItoVYJmjCAMbdRHTSAtt" -X POST -d "user[name]=API User" -d "user[email]=email@api.com" -d "user[tag_list]= tester, new user" -d "attributes[phone]=+123456456" -d "attributes[custom_key]=custom_value" http://smart-mailing.eastus.cloudapp.azure.com/api/v1/users + # == Request Type: + # POST + # == Parameters: + # [String] user[email] User's email (required) + # [String] user[name] User's name (optional) + # [String] user[tag_list] User's tags (optional) + # [String] attributes[key] User's attributes (optional) + def create + user = @api_account.users.new(user_params) + if user.save + if params[:attributes].present? + params[:attributes].keys.each do |key| + user.user_attributes.create(key: key, value: params[:attributes][key]) + end + end + render json: { + user: user.attributes.merge(tags: user.tag_list, atributes: user.user_attributes.pluck(:key, :value) ) + }, status: 200 + else + render json: { errors: user.errors.messages }, status: 422 + end + end + + # Requiered Paramaters for create a User + def user_params + params.require(:user).permit(:name, :email, :tag_list) + end +end \ No newline at end of file diff --git a/app/models/account.rb b/app/models/account.rb index da90a70..b738c1f 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -33,4 +33,11 @@ class Account < ApplicationRecord has_many :smtp_settings has_many :imap_settings has_many :notes + + before_create :set_authentication_token + + private + def set_authentication_token + self.authentication_token = Devise.friendly_token + end end diff --git a/config/routes.rb b/config/routes.rb index 9254f95..6d2b8ee 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -62,6 +62,11 @@ get 'tag_search', to: 'tags#tag_search' get 'documentation', to: 'home#documentation' + namespace :api do + namespace :v1 do + resources :users + end + end # config/routes.rb require "sidekiq/web" diff --git a/db/migrate/20170719120303_add_authentication_token_to_account.rb b/db/migrate/20170719120303_add_authentication_token_to_account.rb new file mode 100644 index 0000000..e05fede --- /dev/null +++ b/db/migrate/20170719120303_add_authentication_token_to_account.rb @@ -0,0 +1,6 @@ +class AddAuthenticationTokenToAccount < ActiveRecord::Migration[5.0] + def change + add_column :accounts, :authentication_token, :string + add_index :accounts, :authentication_token, unique: true + end +end From 5a962fcbc2f3e18aceb137f0ae638aae5925d3aa Mon Sep 17 00:00:00 2001 From: Sadik Ay Date: Wed, 19 Jul 2017 16:44:40 +0300 Subject: [PATCH 08/13] update schema rb --- db/schema.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index 5b1455c..fefc79d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170717125321) do +ActiveRecord::Schema.define(version: 20170719120303) do create_table "accounts", force: :cascade do |t| t.string "email", default: "", null: false @@ -29,6 +29,8 @@ t.string "unconfirmed_email" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "authentication_token" + t.index ["authentication_token"], name: "index_accounts_on_authentication_token", unique: true t.index ["email"], name: "index_accounts_on_email", unique: true end From d902a84330f867cd3286561ee163bde378104c61 Mon Sep 17 00:00:00 2001 From: Sadik Ay Date: Thu, 20 Jul 2017 02:11:50 +0300 Subject: [PATCH 09/13] add link to attributes --- app/views/user_attributes/_attribute_row.html.haml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/views/user_attributes/_attribute_row.html.haml b/app/views/user_attributes/_attribute_row.html.haml index 64829f8..35e93c4 100644 --- a/app/views/user_attributes/_attribute_row.html.haml +++ b/app/views/user_attributes/_attribute_row.html.haml @@ -1,6 +1,10 @@ %tr{id: "attr-#{attr.id}"} %td= editable attr, :key, url: user_user_attribute_path(user, attr), value: attr.key - %td= editable attr, :value, url: user_user_attribute_path(user, attr), value: attr.value + %td + - if attr.value.present? && attr.value.include?('http') + = link_to attr.value, attr.value,target: '_blank' + - else + = editable attr, :value, url: user_user_attribute_path(user, attr), value: attr.value %td{width: "30"} = link_to user_user_attribute_path(user, attr), method: :delete, remote: true, data: { confirm: 'Are you sure?' }, class: '' do %span.fa.fa-trash \ No newline at end of file From bf22e9b9a137043804fa28d0c7293c52e050a060 Mon Sep 17 00:00:00 2001 From: Sadik Ay Date: Thu, 20 Jul 2017 10:49:26 +0300 Subject: [PATCH 10/13] update api url --- app/controllers/api/v1/users_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb index 39b002d..edd8c18 100644 --- a/app/controllers/api/v1/users_controller.rb +++ b/app/controllers/api/v1/users_controller.rb @@ -2,7 +2,7 @@ class Api::V1::UsersController < Api::V1::ApiBaseController # Creates User. # Create a user for authenticated account. # == Example Request - # curl -i -H "Authorization: Token token=7LGWItoVYJmjCAMbdRHTSAtt" -X POST -d "user[name]=API User" -d "user[email]=email@api.com" -d "user[tag_list]= tester, new user" -d "attributes[phone]=+123456456" -d "attributes[custom_key]=custom_value" http://smart-mailing.eastus.cloudapp.azure.com/api/v1/users + # curl -i -H "Authorization: Token token=7LGWItoVYJmjCAMbdRHTSAtt" -X POST -d "user[name]=API User" -d "user[email]=email@api.com" -d "user[tag_list]= tester, new user" -d "attributes[phone]=+123456456" -d "attributes[custom_key]=custom_value" http://localhost:3000/api/v1/users # == Request Type: # POST # == Parameters: From 95e88337a824e78deca5f9afbbf8fde791517f69 Mon Sep 17 00:00:00 2001 From: Sadik Ay Date: Fri, 21 Jul 2017 14:05:14 +0300 Subject: [PATCH 11/13] update docs --- README.md | 7 +++ app/controllers/home_controller.rb | 1 - app/views/home/documentation.html.erb | 83 --------------------------- config/routes.rb | 1 - 4 files changed, 7 insertions(+), 85 deletions(-) delete mode 100644 app/views/home/documentation.html.erb diff --git a/README.md b/README.md index ab53472..1b65c8b 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,13 @@ sudo docker-compose build sudo docker-compose run web rake db:migrate sudo docker-compose up -d ``` +### Configure Sendgrid +If you are using sendgrid as email provider, you will be able to +get status of sent emails. + + + Go to: https://app.sendgrid.com/settings/mail_settings -> + Event Notification -> ``/campaigns/event_receiver ## Tests We used the tool very day, so we test on production :) diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 501c207..0f9ad8b 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -4,5 +4,4 @@ class HomeController < ApplicationController def index; end - def documentation; end end diff --git a/app/views/home/documentation.html.erb b/app/views/home/documentation.html.erb deleted file mode 100644 index 588b2b8..0000000 --- a/app/views/home/documentation.html.erb +++ /dev/null @@ -1,83 +0,0 @@ -
-
-

Smart Email Marketing

-

A simple dockerized rails app to manage your emails and campaigns with taggings.

-

Code Climate

- -

Installation

-

Install Docker

-

Install the most recent version of the Docker Engine for your platform using the official Docker releases, which can also be installed using:

-
wget -qO- https://get.docker.com/ | sh
-  
-

Install Docker Compose

-

Install docker compose from the official page.

-
curl -L "https://github.com/docker/compose/releases/download/1.11.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
-  chmod +x /usr/local/bin/docker-compose
-  
-

Database Settings

-

You can use sqlite, postgresql, mysql and sql server.

-

Create a database.yml and link it in the docker-compose.yml

-

Create data folders

-
mkdir -p /datadrive/csv-files && mkdir -p /datadrive/data/db && mkdir -p /datadrive/data/redis && mkdir -p /datadrive/data/nginx && mkdir -p /datadrive/working-dir
-  
-

Create a database.yml

-
    -
  • Sqlite
  • -
-
cd /datadrive && wget https://raw.githubusercontent.com/mojilala/smart-emailing/master/config/database.yml
-  
-
    -
  • MySQL
  • -
-
cd /datadrive && wget https://raw.githubusercontent.com/mojilala/smart-emailing/master/config/database_mysql.example.yml
-  
-
    -
  • PostgreSQL
  • -
-
cd /datadrive && wget https://raw.githubusercontent.com/mojilala/smart-emailing/master/config/database_postgresql.example.yml
-  
-
    -
  • Sql SERVER
  • -
-
cd /datadrive && wget https://raw.githubusercontent.com/mojilala/smart-emailing/master/config/database_azure_sql.example.yml
-  
-

Create nginx settings

-
cd /datadrive/data/nginx && wget https://raw.githubusercontent.com/mojilala/smart-emailing/master/nginx/my_proxy.conf
-  
-

Get docker-compose.yml

-
    -
  • Download
  • -
-
cd /datadrive/working-dir && wget https://raw.githubusercontent.com/mojilala/smart-emailing/master/docker-compose.yml
-  
- -

Run

-
sudo docker-compose build
-  sudo docker-compose run web rake db:migrate
-  sudo docker-compose up -d
-  
-

Tests

-

We used the tool very day, so we test on production :)
- There are no tests. any test contrubtions are verywelcome.

-

Contributing

-
    -
  1. Fork it
  2. -
  3. Create your feature branch (git checkout -b my-new-feature)
  4. -
  5. Commit your changes (git commit -am 'Add some feature')
  6. -
  7. Push to the branch (git push origin my-new-feature)
  8. -
  9. Create new Pull Request
  10. -
-

Created by

- -

Developed by

- -
-
- diff --git a/config/routes.rb b/config/routes.rb index 373f2c2..430b8a2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -61,7 +61,6 @@ resources :notes get 'tag_search', to: 'tags#tag_search' - get 'documentation', to: 'home#documentation' namespace :api do namespace :v1 do From ea22b19e973ee1683d9c7192f1b82f1083f3b2af Mon Sep 17 00:00:00 2001 From: Sadik Ay Date: Fri, 21 Jul 2017 16:19:11 +0300 Subject: [PATCH 12/13] add api doc to app --- app/assets/stylesheets/application.scss | 4 ++ app/views/campaigns/index.html.haml | 4 -- app/views/layouts/welcome.html.haml | 5 --- app/views/users/_basic_search.html.haml | 48 ----------------------- app/views/users/_export_buttons.html.haml | 7 ++++ app/views/users/detailed_list.html.haml | 18 +-------- app/views/users/import.html.haml | 14 ++++--- app/views/users/index.html.haml | 17 +------- app/views/users/new.html.haml | 32 +++++++++++++-- 9 files changed, 52 insertions(+), 97 deletions(-) delete mode 100644 app/views/users/_basic_search.html.haml create mode 100644 app/views/users/_export_buttons.html.haml diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index a0b85ed..3588c18 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -31,3 +31,7 @@ .btn-info { background-color: #2b9cbd; } +.large-data-table { + display: block; + overflow-x: auto; + } \ No newline at end of file diff --git a/app/views/campaigns/index.html.haml b/app/views/campaigns/index.html.haml index 473011a..3d93f7e 100644 --- a/app/views/campaigns/index.html.haml +++ b/app/views/campaigns/index.html.haml @@ -1,9 +1,6 @@ = page_title 'Campaigns' .x_panel - .x_title - %h4 Campaigns - .x_content = render partial: 'shared/advanced_search', locals: { form_url: nil } %hr/ @@ -34,4 +31,3 @@ %fa.fa.fa-eye = link_to campaign, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-sm btn-danger btn-xs' do %fa.fa.fa-trash - diff --git a/app/views/layouts/welcome.html.haml b/app/views/layouts/welcome.html.haml index 7ab3a04..e940629 100644 --- a/app/views/layouts/welcome.html.haml +++ b/app/views/layouts/welcome.html.haml @@ -22,11 +22,6 @@ %span.icon-bar %span.icon-bar %a.navbar-brand.topnav{:href => "/"} Smart Email Marketing - / Collect the nav links, forms, and other content for toggling - #bs-example-navbar-collapse-1.collapse.navbar-collapse - %ul.nav.navbar-nav.navbar-right - %li - %a{:href => "/documentation"} Documentation = yield diff --git a/app/views/users/_basic_search.html.haml b/app/views/users/_basic_search.html.haml deleted file mode 100644 index 9409e12..0000000 --- a/app/views/users/_basic_search.html.haml +++ /dev/null @@ -1,48 +0,0 @@ -= search_form_for @q do |f| - %table.table.table-condensed.table-bordered - %tbody - %tr - %td - %table.table.table-condensed.table-hover.table-bordered - %tbody - %tr - %td= f.label :name_cont - %td= f.search_field :name_cont, class: 'form-control' - %tr - %td= f.label :user_attributes_key_eq - %td= f.search_field :user_attributes_key_eq, class: 'form-control' - %tr - %td= f.label :user_attributes_value_eq - %td= f.search_field :user_attributes_value_eq, class: 'form-control' - %tr - %td= f.label :email_cont - %td= f.search_field :email_cont, class: 'form-control' - %tr - %td= f.label :tags_name_in - %td= f.select :tags_name_in, options_for_select(@all_tags.pluck(:name).map{ |t| [t.humanize, t] }, @q.tags_name_in), {}, { class: 'select2', multiple: true, include_blank: true } - %tr - %tr - %td= f.label :campaigns_name_in - %td= f.select :campaigns_name_in, options_for_select(current_account.campaigns.pluck(:name).map{ |c| [c.humanize, c] }, @q.campaigns_name_in), {}, { class: 'select2', multiple: true, include_blank: true } - %tr - %td= f.label :campaign_tags_name_in - %td= f.select :campaigns_tags_name_in, options_for_select(@all_tags.pluck(:name).map{ |t| [t.humanize, t] }, @q.campaigns_tags_name_in), {}, { class: 'select2', multiple: true, include_blank: true } - %tr - %td= f.label :campaign_email_status_eq - %td= f.select :campaign_users_status_in, options_for_select(CampaignUser::STATUSES, {}, { class: 'select2', multiple: true, include_blank: true } - %tr - %td - %b Filter Limit - %small (Maximum users count) - %td= number_field_tag 'limit_count', params[:limit_count], class: 'form-control' - %tr - %td= f.label :created_at_greater_than - %td= f.date_field :created_at_gt, class: 'form-control' - %tr - %td= f.label :email_sent_at_greater_than - %td= f.date_field :campaign_users_sent_at_gt, class: 'form-control' - Grouping Combinator: - .btn= f.select :m, options_for_select(%w(and or).map{ |ps| [ps, ps] }, @q.m), include_blank: false - - = f.submit "Search", class: 'btn btn-info' - = link_to 'Clear', users_path, class: 'btn btn-warning actions' diff --git a/app/views/users/_export_buttons.html.haml b/app/views/users/_export_buttons.html.haml new file mode 100644 index 0000000..b3ad41f --- /dev/null +++ b/app/views/users/_export_buttons.html.haml @@ -0,0 +1,7 @@ += content_for :extra_buttons_in_search do + = link_to (request.fullpath + '?&format=csv'), class: 'btn btn-default' do + %i.fa.fa-external-link + Export to CSV + = link_to (request.fullpath + '?&format=xlsx'), class: 'btn btn-default' do + %i.fa.fa-external-link + Export to Excel \ No newline at end of file diff --git a/app/views/users/detailed_list.html.haml b/app/views/users/detailed_list.html.haml index 5e37568..ab93dd0 100644 --- a/app/views/users/detailed_list.html.haml +++ b/app/views/users/detailed_list.html.haml @@ -1,15 +1,6 @@ -= content_for :extra_buttons_in_search do - = link_to (request.fullpath + '?&format=csv'), class: 'btn btn-default' do - %i.fa.fa-external-link - Export to CSV - = link_to (request.fullpath + '?&format=xlsx'), class: 'btn btn-default' do - %i.fa.fa-external-link - Export to Excel - - += render 'users/export_buttons' = page_title 'Detailed Users' - = content_for :page_title_right do = link_to new_user_path do %button.btn.btn-primary @@ -21,17 +12,13 @@ .row .col-md-12 .x_panel - .x_title - %h4 Detailed Users .x_content - = render partial: 'shared/advanced_search', locals: { form_url: detailed_list_users_path } - = render 'create_campaign_buttons' = paginate @users - %table.table.table-striped.table-bordered.table-hover{style: 'background-color: white;'} + %table.table.table-striped.table-bordered.table-hover.large-data-table %thead %tr %th{width: "200"} Email @@ -49,7 +36,6 @@ %div{id: "UserTags-#{user.id}"} = render partial: 'tags/item_tags', locals: { item: user } %td= user.name - %td - user.campaigns.each do |cp| = link_to "##{cp.id},", campaign_path(cp), 'data-toggle': 'tooltip', 'data-placement': 'top', 'data-original-title': "#{cp.name}" diff --git a/app/views/users/import.html.haml b/app/views/users/import.html.haml index cafed43..c184ea3 100644 --- a/app/views/users/import.html.haml +++ b/app/views/users/import.html.haml @@ -1,16 +1,20 @@ += page_title 'Import Users From File' += content_for :page_title_right do + = link_to new_user_path do + %button.btn.btn-primary + %span.fa.fa-plus + New User + .x_panel = form_tag users_path, method: :post, multipart: true do - = label_tag 'Import Users From CSV File' + = label_tag 'File' = file_field_tag :file, class: 'form-control' = label_tag 'Tags' = select_tag :tags, options_for_select(@all_tags.map{ |t| [t, t] }), { include_blank: false, class: 'select2', multiple: true } .actions - .col-md-6 - = submit_tag 'Import User List', class: 'btn btn-primary' - .col-md-6.text-right - = link_to 'Add Single User', new_user_path, class: 'btn btn-default' + = submit_tag 'Import User List', class: 'btn btn-primary' .col-sm-12 Example users csv diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml index 458f644..4aa82f7 100644 --- a/app/views/users/index.html.haml +++ b/app/views/users/index.html.haml @@ -1,15 +1,6 @@ -= content_for :extra_buttons_in_search do - = link_to (request.fullpath + '?&format=csv'), class: 'btn btn-default' do - %i.fa.fa-external-link - Export to CSV - = link_to (request.fullpath + '?&format=xlsx'), class: 'btn btn-default' do - %i.fa.fa-external-link - Export to Excel - - += render 'users/export_buttons' = page_title 'Users' - = content_for :page_title_right do = link_to new_user_path do %button.btn.btn-primary @@ -19,10 +10,7 @@ .row .col-md-12 .x_panel - .x_title - %h4 Users .x_content - = render partial: 'shared/advanced_search', locals: { form_url: nil } = render 'create_campaign_buttons' @@ -46,7 +34,6 @@ %div{id: "UserTags-#{user.id}"} = render partial: 'tags/item_tags', locals: { item: user } %td= user.name - %td - user.campaigns.each do |cp| = link_to "##{cp.id},", campaign_path(cp), 'data-toggle': 'tooltip', 'data-placement': 'top', 'data-original-title': "#{cp.name}" @@ -58,4 +45,4 @@ = link_to user_path(user), class: 'btn btn-default btn-xs' do %i.fa.fa-eye - = paginate @users \ No newline at end of file + = paginate @users diff --git a/app/views/users/new.html.haml b/app/views/users/new.html.haml index 04f639c..dc52b2e 100644 --- a/app/views/users/new.html.haml +++ b/app/views/users/new.html.haml @@ -1,9 +1,7 @@ += page_title 'New User' .row .col-sm-8 .x_panel - .x_title - %h4 New User - = form_tag create_single_users_path, id: 'single-user', method: :post do = label_tag 'Name (optional)' @@ -20,4 +18,30 @@ .col-sm-4 = link_to 'Import Users From CSV or XLS files', import_users_path, class: 'btn btn-default' - = link_to 'Create Users Over API', '#', class: 'btn btn-default' + %button.btn.btn-default{"data-target" => ".bs-api-modal-sm", "data-toggle" => "modal", :type => "button"} Create Users Over API + +.modal.fade.bs-api-modal-sm{"aria-hidden" => "true", :role => "dialog", :tabindex => "-1"} + .modal-dialog.modal-lg + .modal-content + .modal-header + %button.close{"aria-label" => "Close", "data-dismiss" => "modal", :type => "button"} + %span{"aria-hidden" => "true"} × + %h4#myModalLabel2.modal-title Create Users Over API + .modal-body + %h4 + Your authentication token: + %mark= current_account.authentication_token + %h4 + %mark.text-success POST /api/v1/users + %h4 Parameters: + %p String: user[email] -> required. Example: test@example.com + %p String: user[name] -> optional. Example: Api User + %p String: user[tag_list] -> optional. Example: new tag, api-users, campaigns + %p String: attribute[custom_data_key] -> optional. Example: attribute[phone]: +11234543, attribute[location]: USA + %h4 + Example Request: + %mark.text-danger + curl -i -H "Authorization: Token token= + = current_account.authentication_token + " -X POST -d "user[name]=API User" -d "user[email]=email@api.com" -d "user[tag_list]= tester, new user" -d "attributes[phone]=+123456456" -d "attributes[custom_key]=custom_value" + = "#{request.base_url}/api/v1/users" From 79051ff0fc728621cf63a4fd56775f67c86b973f Mon Sep 17 00:00:00 2001 From: Sadik Ay Date: Fri, 21 Jul 2017 18:10:10 +0300 Subject: [PATCH 13/13] cleanup campaign status boxes --- app/helpers/campaigns_helper.rb | 16 ++++ app/views/campaigns/_stats.html.haml | 90 +++---------------- app/views/campaigns/new.html.haml | 7 +- app/views/email_templates/_form.html.haml | 8 +- app/views/email_templates/index.html.haml | 2 - app/views/imap_settings/_form.html.haml | 7 +- app/views/notes/_form.html.haml | 7 +- app/views/notes/index.html.haml | 15 ++-- .../shared/_form_error_explanation.html.haml | 6 ++ app/views/smtp_settings/_form.html.haml | 71 +++++++-------- app/views/tags/index.html.haml | 2 +- 11 files changed, 76 insertions(+), 155 deletions(-) create mode 100644 app/views/shared/_form_error_explanation.html.haml diff --git a/app/helpers/campaigns_helper.rb b/app/helpers/campaigns_helper.rb index d9089a0..7fd6a1e 100644 --- a/app/helpers/campaigns_helper.rb +++ b/app/helpers/campaigns_helper.rb @@ -1,2 +1,18 @@ module CampaignsHelper + def status_card(display_text, count, status_percent) + content_tag :div, class: 'col-md-2 col-sm-4 col-xs-6 tile_stats_count' do + (content_tag :span, class: 'count_top' do + concat (display_text) + end) + + + (content_tag :div, class: 'count' do + count.to_s + end) + + + (content_tag :span, class: 'count_bottom' do + content_tag :i, class: 'content' + "#{status_percent} %" + end) + end + end end diff --git a/app/views/campaigns/_stats.html.haml b/app/views/campaigns/_stats.html.haml index 26edb8a..8e42ea8 100644 --- a/app/views/campaigns/_stats.html.haml +++ b/app/views/campaigns/_stats.html.haml @@ -1,94 +1,24 @@ .row.tile_count .col-md-1 - .col-md-2.col-sm-4.col-xs-6.tile_stats_count - %span.count_top - %i.fa.fa-user - Draft - .count= @stats['draft'] || 0 - %span.count_bottom - %i.green - = "#{Campaign.calculate_percent(@stats['draft'], @total_users_count).to_i} %" + = status_card('Draft', (@stats['draft'] || 0), Campaign.calculate_percent(@stats['draft'], @total_users_count).to_i) - .col-md-2.col-sm-4.col-xs-6.tile_stats_count - %span.count_top - %i.fa.fa-user - Processed - .count.green= @stats['processed'] || 0 - %span.count_bottom - %i.green - = "#{Campaign.calculate_percent(@stats['processed'] , @total_users_count).to_i} %" + = status_card('Processed', (@stats['processed'] || 0), Campaign.calculate_percent(@stats['processed'], @total_users_count).to_i) - .col-md-2.col-sm-4.col-xs-6.tile_stats_count - %span.count_top - %i.fa.fa-user - Dropped - .count= @stats['dropped'] || 0 - %span.count_bottom - %i.green - = "#{Campaign.calculate_percent(@stats['dropped'] , @total_users_count).to_i} %" + = status_card('Dropped', (@stats['dropped'] || 0), Campaign.calculate_percent(@stats['dropped'], @total_users_count).to_i) - .col-md-2.col-sm-4.col-xs-6.tile_stats_count - %span.count_top - %i.fa.fa-user - Delivered - .count= @stats['delivered'] || 0 - %span.count_bottom - %i.green - = "#{Campaign.calculate_percent(@stats['delivered'] , @total_users_count).to_i} %" + = status_card('Delivered', (@stats['delivered'] || 0), Campaign.calculate_percent(@stats['delivered'], @total_users_count).to_i) - .col-md-2.col-sm-4.col-xs-6.tile_stats_count - %span.count_top - %i.fa.fa-user - Deferred - .count= @stats['deferred'] || 0 - %span.count_bottom - %i.green - = "#{Campaign.calculate_percent(@stats['deferred'] , @total_users_count).to_i} %" + = status_card('Deferred', (@stats['deferred'] || 0), Campaign.calculate_percent(@stats['deferred'], @total_users_count).to_i) .row.tile_count .col-md-1 - .col-md-2.col-sm-4.col-xs-6.tile_stats_count - %span.count_top - %i.fa.fa-user - Bounced - .count= @stats['bounce'] || 0 - %span.count_bottom - %i.green - = "#{Campaign.calculate_percent(@stats['bounce'], @total_users_count).to_i} %" + = status_card('Bounced', (@stats['bounce'] || 0), Campaign.calculate_percent(@stats['bounce'], @total_users_count).to_i) - .col-md-2.col-sm-4.col-xs-6.tile_stats_count - %span.count_top - %i.fa.fa-user - Opened - .count.green= @stats['open'] || 0 - %span.count_bottom - %i.green - = "#{Campaign.calculate_percent(@stats['open'] , @total_users_count).to_i} %" + = status_card('Opened', (@stats['open'] || 0), Campaign.calculate_percent(@stats['open'], @total_users_count).to_i) - .col-md-2.col-sm-4.col-xs-6.tile_stats_count - %span.count_top - %i.fa.fa-user - Clicked - .count= @stats['click'] || 0 - %span.count_bottom - %i.green - = "#{Campaign.calculate_percent(@stats['click'] , @total_users_count).to_i} %" + = status_card('Clicked', (@stats['click'] || 0), Campaign.calculate_percent(@stats['click'], @total_users_count).to_i) - .col-md-2.col-sm-4.col-xs-6.tile_stats_count - %span.count_top - %i.fa.fa-user - Spamreport - .count= @stats['spamreport'] || 0 - %span.count_bottom - %i.green - = "#{Campaign.calculate_percent(@stats['spamreport'] , @total_users_count).to_i} %" + = status_card('Spam', (@stats['spamreport'] || 0), Campaign.calculate_percent(@stats['spamreport'], @total_users_count).to_i) - .col-md-2.col-sm-4.col-xs-6.tile_stats_count - %span.count_top - %i.fa.fa-user - Unsubscribed - .count= @stats['unsubscribe'] || 0 - %span.count_bottom - %i.green - = "#{Campaign.calculate_percent(@stats['unsubscribe'] , @total_users_count).to_i} %" + = status_card('Unsubscribed', (@stats['unsubscribe'] || 0), Campaign.calculate_percent(@stats['unsubscribe'], @total_users_count).to_i) .col-md-1 diff --git a/app/views/campaigns/new.html.haml b/app/views/campaigns/new.html.haml index 79fe6b8..1e7f507 100644 --- a/app/views/campaigns/new.html.haml +++ b/app/views/campaigns/new.html.haml @@ -2,12 +2,7 @@ .x_panel = form_for @campaign do |f| - - if @campaign.errors.any? - #error_explanation - %h2= "#{pluralize(@campaign.errors.count, "error")} prohibited this campaign from being saved:" - %ul - - @campaign.errors.full_messages.each do |msg| - %li= msg + = render partial: 'shared/form_error_explanation', locals: { source: @campaign } = f.label :name = f.text_field :name, class: 'form-control' diff --git a/app/views/email_templates/_form.html.haml b/app/views/email_templates/_form.html.haml index 826092f..a0ba00a 100644 --- a/app/views/email_templates/_form.html.haml +++ b/app/views/email_templates/_form.html.haml @@ -1,12 +1,6 @@ .col-md-12.content-box-large.panel-heading = form_for @email_template do |f| - - if @email_template.errors.any? - #error_explanation - %h2= "#{pluralize(@email_template.errors.count, "error")} prohibited this email_template from being saved:" - %ul - - @email_template.errors.full_messages.each do |msg| - %li= msg - + = render partial: 'shared/form_error_explanation', locals: { source: @email_template } = f.label 'Mail Subject' = f.text_field :subject, class: 'form-control' diff --git a/app/views/email_templates/index.html.haml b/app/views/email_templates/index.html.haml index 3093c69..5cf06e8 100644 --- a/app/views/email_templates/index.html.haml +++ b/app/views/email_templates/index.html.haml @@ -8,8 +8,6 @@ .x_panel - .x_title - %h4 Email Templates .x_content %table.table.table-striped.table-bordered.table-hover %thead diff --git a/app/views/imap_settings/_form.html.haml b/app/views/imap_settings/_form.html.haml index 541f549..43275d0 100644 --- a/app/views/imap_settings/_form.html.haml +++ b/app/views/imap_settings/_form.html.haml @@ -1,12 +1,7 @@ .col-md-6 .x_panel = form_for @imap_setting do |f| - - if @imap_setting.errors.any? - #error_explanation - %h2= "#{pluralize(@imap_setting.errors.count, "error")} prohibited this SMTP Setting from being saved:" - %ul - - @imap_setting.errors.full_messages.each do |msg| - %li= msg + = render partial: 'shared/form_error_explanation', locals: { source: @imap_setting } .field = f.label 'IMAP address' diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index 583ce3f..c4e26ec 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -1,11 +1,6 @@ .col-md-12.x_panel = form_for @note do |f| - - if @note.errors.any? - #error_explanation - %h2= "#{pluralize(@note.errors.count, "error")} prohibited this note from being saved:" - %ul - - @note.errors.full_messages.each do |msg| - %li= msg + = render partial: 'shared/form_error_explanation', locals: { source: @note } .field = f.label :title diff --git a/app/views/notes/index.html.haml b/app/views/notes/index.html.haml index 94de627..c4b861c 100644 --- a/app/views/notes/index.html.haml +++ b/app/views/notes/index.html.haml @@ -1,11 +1,10 @@ -%div - .page-title - .title_left - %h3 Listing Notes - .title_right - .col-md-12.col-sm-12.col-xs-12.text-right - = link_to new_note_path do - %button.btn.btn-primary New Note += page_title 'Listing Notes' +- content_for :page_title_right do + = link_to new_note_path do + %button.btn.btn-primary + %fa.fa.fa-plus + New Note + .clearfix .x_panel %table.table.table-striped.projects diff --git a/app/views/shared/_form_error_explanation.html.haml b/app/views/shared/_form_error_explanation.html.haml new file mode 100644 index 0000000..c8a91ad --- /dev/null +++ b/app/views/shared/_form_error_explanation.html.haml @@ -0,0 +1,6 @@ +- if source.errors.any? + #error_explanation + %h2= "#{pluralize(source.errors.count, "error")} prohibited this campaign from being saved:" + %ul + - source.errors.full_messages.each do |msg| + %li= msg \ No newline at end of file diff --git a/app/views/smtp_settings/_form.html.haml b/app/views/smtp_settings/_form.html.haml index 8e78fa6..478b185 100644 --- a/app/views/smtp_settings/_form.html.haml +++ b/app/views/smtp_settings/_form.html.haml @@ -1,42 +1,35 @@ .row - .col-md-12 + .col-md-6 .x_panel - .col-md-6 - .x_panel - .x_content - = form_for @smtp_setting do |f| - - if @smtp_setting.errors.any? - #error_explanation - %h2= "#{pluralize(@smtp_setting.errors.count, "error")} prohibited this SMTP Setting from being saved:" - %ul - - @smtp_setting.errors.full_messages.each do |msg| - %li= msg + .x_content + = form_for @smtp_setting do |f| + = render partial: 'shared/form_error_explanation', locals: { source: @smtp_setting } - .field - = f.label :from_email - = f.text_field :from_email, class: 'form-control', required: true, placeholder: 'email@example.com' - .field - = f.label :reply_to - = f.text_field :reply_to, class: 'form-control', required: true, placeholder: 'support@example.com' - .field - = f.label :provider - = f.text_field :provider, class: 'form-control', required: true, placeholder: 'sendgrid, google, outlook etc...' - .field - = f.label :address - = f.text_field :address, class: 'form-control', required: true, placeholder: 'smtp.sendgrid.net' - .field - = f.label :port - = f.text_field :port, class: 'form-control', required: true, placeholder: '587' - .field - = f.label :domain - = f.text_field :domain, class: 'form-control', required: true, placeholder: 'email-domain.com' - .field - = f.label :username - = f.text_field :username, class: 'form-control', required: true - .field - = f.label :password - = f.password_field :password, class: 'form-control', required: true - .actions - = f.submit 'Save', class: 'btn btn-primary' - = link_to 'Cancel', smtp_settings_path, class: 'btn btn-default pull-right' - .clearfix + .field + = f.label :from_email + = f.text_field :from_email, class: 'form-control', required: true, placeholder: 'email@example.com' + .field + = f.label :reply_to + = f.text_field :reply_to, class: 'form-control', required: true, placeholder: 'support@example.com' + .field + = f.label :provider + = f.text_field :provider, class: 'form-control', required: true, placeholder: 'sendgrid, google, outlook etc...' + .field + = f.label :address + = f.text_field :address, class: 'form-control', required: true, placeholder: 'smtp.sendgrid.net' + .field + = f.label :port + = f.text_field :port, class: 'form-control', required: true, placeholder: '587' + .field + = f.label :domain + = f.text_field :domain, class: 'form-control', required: true, placeholder: 'email-domain.com' + .field + = f.label :username + = f.text_field :username, class: 'form-control', required: true + .field + = f.label :password + = f.password_field :password, class: 'form-control', required: true + .actions + = f.submit 'Save', class: 'btn btn-primary pull-right' + = link_to 'Cancel', smtp_settings_path, class: 'btn btn-default pull-left' + .clearfix diff --git a/app/views/tags/index.html.haml b/app/views/tags/index.html.haml index 6ee3f8b..87a3b04 100644 --- a/app/views/tags/index.html.haml +++ b/app/views/tags/index.html.haml @@ -1,5 +1,5 @@ += page_title "Tag Managment" .x_panel - %h3 Tags Managment .col-md-12.content-box-large.panel-heading %p.text-muted Click on tag name to edit. %table#example.table.table-striped.table-bordered{:border => "0", :cellpadding => "0", :cellspacing => "0"}