Add export and import and batch delete subscribers feature.
This commit is contained in:
parent
bb3236feba
commit
4735b107d7
|
@ -25,4 +25,87 @@ class Admin::EPaperSubscribersController < OrbitAdminController
|
||||||
end
|
end
|
||||||
redirect_to admin_e_paper_subscribers_path
|
redirect_to admin_e_paper_subscribers_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def export_excel
|
||||||
|
@epaper_subscribers = EPaperSubscriber.where(:email.nin=>[nil,""]).desc(:created_at)
|
||||||
|
@subscribers = @epaper_subscribers.where(:subscribed.ne=>false)
|
||||||
|
@unsubscribers = @epaper_subscribers.where(:subscribed=>false)
|
||||||
|
respond_to do |format|
|
||||||
|
format.xlsx {
|
||||||
|
response.headers['Content-Disposition'] = 'attachment; filename="'+Site.first.title+'-'+I18n.t('e_paper.e_paper')+'-'+I18n.t('e_paper.subscriber')+'.xlsx"'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
def get_subscribers_modal
|
||||||
|
@epaper_subscribers = EPaperSubscriber.where(:email.nin=>[nil,""]).desc(:created_at)
|
||||||
|
@subscribers = @epaper_subscribers.where(:subscribed.ne=>false)
|
||||||
|
@unsubscribers = @epaper_subscribers.where(:subscribed=>false)
|
||||||
|
render :partial => 'modal_select', :layout => false
|
||||||
|
end
|
||||||
|
def import_from_excel
|
||||||
|
workbook = RubyXL::Parser.parse(params["import_file"].tempfile)
|
||||||
|
subscribe_sheet = workbook['Subscribe']
|
||||||
|
unsubscribe_sheet = workbook['Unsubscribe']
|
||||||
|
subscribe_sheet.each_with_index do |row, i|
|
||||||
|
next if i < 1
|
||||||
|
c0 = row.cells[0]
|
||||||
|
c1 = row.cells[1]
|
||||||
|
if c0
|
||||||
|
email = c0.value
|
||||||
|
if email.present?
|
||||||
|
subscriber = EPaperSubscriber.where(:email=>email).first
|
||||||
|
if subscriber.nil?
|
||||||
|
subscriber = EPaperSubscriber.new(:email=>email)
|
||||||
|
end
|
||||||
|
language = c1.value
|
||||||
|
if language.blank?
|
||||||
|
language = I18n.locale.to_s
|
||||||
|
end
|
||||||
|
subscriber.subscribed = true
|
||||||
|
subscriber.language = language
|
||||||
|
subscriber.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
unsubscribe_sheet.each_with_index do |row, i|
|
||||||
|
next if i < 1
|
||||||
|
c0 = row.cells[0]
|
||||||
|
c1 = row.cells[1]
|
||||||
|
if c0
|
||||||
|
email = c0.value
|
||||||
|
if email.present?
|
||||||
|
subscriber = EPaperSubscriber.where(:email=>email).first
|
||||||
|
if subscriber.nil?
|
||||||
|
subscriber = EPaperSubscriber.new(:email=>email)
|
||||||
|
end
|
||||||
|
language = c1.value
|
||||||
|
if language.blank?
|
||||||
|
language = I18n.locale.to_s
|
||||||
|
end
|
||||||
|
subscriber.subscribed = false
|
||||||
|
subscriber.language = language
|
||||||
|
subscriber.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
redirect_to admin_e_paper_subscribers_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def download_excel_format
|
||||||
|
@subscribers = []
|
||||||
|
@unsubscribers = []
|
||||||
|
respond_to do |format|
|
||||||
|
format.xlsx {
|
||||||
|
response.headers['Content-Disposition'] = 'attachment; filename="'+Site.first.title+'-'+I18n.t('e_paper.e_paper')+'-'+I18n.t('e_paper.subscriber')+'excel_format.xlsx"'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_subscribers
|
||||||
|
subscriber_ids = params['subscriber_ids']
|
||||||
|
if subscriber_ids
|
||||||
|
EPaperSubscriber.where(:id.in=>subscriber_ids).destroy
|
||||||
|
end
|
||||||
|
redirect_to admin_e_paper_subscribers_path
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -269,6 +269,8 @@ class EPapersController < ApplicationController
|
||||||
subscriber.subscribed = false
|
subscriber.subscribed = false
|
||||||
subscriber.save
|
subscriber.save
|
||||||
data = {"success" => true, "msg" => "Successfully Unsubscribed!!!"}
|
data = {"success" => true, "msg" => "Successfully Unsubscribed!!!"}
|
||||||
|
else
|
||||||
|
data = {"success" => false, "msg" => "You are not a subscriber!!!"}
|
||||||
end
|
end
|
||||||
render :json => data.to_json
|
render :json => data.to_json
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,5 +28,24 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div class="bottomnav clearfix" style="left: 81px;">
|
<div class="bottomnav clearfix" style="left: 81px;">
|
||||||
<%= content_tag :div, paginate(@subscribers), class: "pagination pagination-centered" %>
|
<%= content_tag(:div, paginate(@subscribers), class: "pagination pagination-centered") %>
|
||||||
|
<div class="pull-right">
|
||||||
|
<%=
|
||||||
|
content_tag(:div, link_to(t("e_paper.export"), admin_e_paper_subscribers_export_excel_path + '.xlsx', :class=>"btn btn-success"), class: "pull-right")
|
||||||
|
%>
|
||||||
|
<div class="dropup upload-button pull-right">
|
||||||
|
<button class="btn btn-info dropdown-toggle" type="button" data-toggle="dropdown">
|
||||||
|
<i class="icon-upload-alt icon-white"></i><%= t('personal_journal.upload') %>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu upload-box">
|
||||||
|
<form action="<%=admin_e_paper_subscribers_import_from_excel_path%>" method="post" enctype="multipart/form-data">
|
||||||
|
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
|
||||||
|
<input type="file" name="import_file" >
|
||||||
|
<button class="btn btn-primary" type="submit"><%= t(:submit) %></button>
|
||||||
|
<a class="" href="<%=admin_e_paper_subscribers_download_excel_format_path%>.xlsx">Download excel format</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -0,0 +1,202 @@
|
||||||
|
<style>
|
||||||
|
.checkbox-card .hide{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="member-filter" class="modal hide fade" tabindex="-1" role="dialog" data-backdrop="true">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h3><%= t('e_paper.subscribers') %></h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="tabbable tabs-left">
|
||||||
|
<div class="nano">
|
||||||
|
<div class="content">
|
||||||
|
<ul class="nav nav-pills nav-stacked">
|
||||||
|
<li class="active"><a href="#epaper_subscribed" data-toggle="tab">Subscribed</a></li>
|
||||||
|
<li><a href="#epaper_unsubscribed" data-toggle="tab">Unsubscribed</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab-content tab-content-1">
|
||||||
|
<div class="tab-pane fade in active" id="epaper_subscribed">
|
||||||
|
<div id="subscribers_form">
|
||||||
|
<fieldset class="clearfix">
|
||||||
|
<div class="member-filter-result nano">
|
||||||
|
<div class="content">
|
||||||
|
<i class="icon-search"></i>
|
||||||
|
<input class="search_emails" placeholder="<%=t('email')%>" title="<%=t('email')%>">
|
||||||
|
<div style="margin-bottom: 1em;"></div>
|
||||||
|
<ul class="checkbox-card clearfix">
|
||||||
|
<% @subscribers.each do |subscriber| %>
|
||||||
|
<li class="check-item">
|
||||||
|
<label class="checkbox inline">
|
||||||
|
<span class="subscriber_email"><%= subscriber.email %></span>
|
||||||
|
<%= check_box_tag 'subscriber_ids[]', subscriber.id, false , :id => "subscriber_ids_#{subscriber.id}" %>
|
||||||
|
<%= hidden_field_tag 'subscriber_ids[]', subscriber.id %>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-actions">
|
||||||
|
<div class="btn-group dropup" style="text-align:left;">
|
||||||
|
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
|
||||||
|
Select
|
||||||
|
<span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#" class="select_all_modal"><i class="icon-ok"></i> Select All</a></li>
|
||||||
|
<li><a href="#" class="deselect_all_modal"><i class="icon-remove"></i> De-select All</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn" data-dismiss="modal"><%= t(:cancel) %></button>
|
||||||
|
<%= submit_tag t(:confirm), class: "btn btn-primary" %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane fade" id="epaper_unsubscribed">
|
||||||
|
<div id="subscribers_form">
|
||||||
|
<fieldset class="clearfix">
|
||||||
|
<div class="member-filter-result nano">
|
||||||
|
<div class="content">
|
||||||
|
<i class="icon-search"></i>
|
||||||
|
<input class="search_emails" placeholder="<%=t('email')%>" title="<%=t('email')%>">
|
||||||
|
<div style="margin-bottom: 1em;"></div>
|
||||||
|
<ul class="checkbox-card clearfix">
|
||||||
|
<% @unsubscribers.each do |unsubscriber| %>
|
||||||
|
<li class="check-item">
|
||||||
|
<label class="checkbox inline">
|
||||||
|
<span class="subscriber_email"><%= unsubscriber.email %></span>
|
||||||
|
<%= check_box_tag 'subscriber_ids[]', unsubscriber.id, false , :id => "subscriber_ids_#{unsubscriber.id}" %>
|
||||||
|
<%= hidden_field_tag 'subscriber_ids[]', unsubscriber.id %>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-actions">
|
||||||
|
<div class="btn-group dropup" style="text-align:left;">
|
||||||
|
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
|
||||||
|
Select
|
||||||
|
<span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#" class="select_all_modal"><i class="icon-ok"></i> Select All</a></li>
|
||||||
|
<li><a href="#" class="deselect_all_modal"><i class="icon-remove"></i> De-select All</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn" data-dismiss="modal"><%= t(:cancel) %></button>
|
||||||
|
<%= submit_tag t(:confirm), class: "btn btn-primary" %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
.checkbox-card li .member-pic {
|
||||||
|
float: left;
|
||||||
|
margin-right: 5px;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#member-filter').on('show.bs.modal', function() {
|
||||||
|
$('#member-filter').off('show.bs.modal');
|
||||||
|
$(this).find('.nano').nanoScroller({ scrollTop: 0, iOSNativeScrolling: true });
|
||||||
|
$(this).find('.checkbox-card').cardCheck();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function encode_str(rawStr){
|
||||||
|
var encodedStr = rawStr.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
|
||||||
|
return '&#' + i.charCodeAt(0) + ';';
|
||||||
|
});
|
||||||
|
return encodedStr;
|
||||||
|
}
|
||||||
|
function generate_member_card(role_id,member_id,member_name,member_pic_url){
|
||||||
|
return ('<li class="filter-item selected_item selected_member check-item" id="'+member_id+'">'+
|
||||||
|
'<label>'+
|
||||||
|
'<img alt="Member pic" class="member-pic" src="'+member_pic_url+'">'+
|
||||||
|
'<span class="user-name" style="position: absolute;margin-left: 45px;">'+encode_str(member_name)+'</span>'+
|
||||||
|
'</label>'+
|
||||||
|
'<input name="<%=role_field_name rescue 'role_ids[]'%>" type="hidden" value='+role_id+'>'+
|
||||||
|
'<input name="<%=member_field_name rescue 'member_ids[]'%>" type="hidden" value='+member_id+'>'+
|
||||||
|
'<input type="checkbox">'+
|
||||||
|
'</li>')
|
||||||
|
};
|
||||||
|
function generate_role_card(role_id,role_name,member_infos){
|
||||||
|
if(member_infos.length == 0)
|
||||||
|
return "";
|
||||||
|
else{
|
||||||
|
var member_cards = "";
|
||||||
|
var fa = '<span style="top: 0.8em;position: absolute;right: 0.3em; font-family: FontAwesome;cursor: pointer;" class="fa fa-caret-down"></span>';
|
||||||
|
member_infos.forEach(function(member_info){
|
||||||
|
member_cards += generate_member_card(role_id,member_info.member_id,member_info.member_name,member_info.member_pic_url);
|
||||||
|
});
|
||||||
|
return ('<li class="selected_item selected_role role" id="'+role_id+'" style="height: unset;"><div class="selected">'+
|
||||||
|
'<label>' +
|
||||||
|
'<span class="role-name">' + role_name + '</span>'+
|
||||||
|
'<span class="badge badge-info" style="position: absolute;right: 1.5em;">' + member_infos.length + '</span>' +
|
||||||
|
'</label>' +
|
||||||
|
'<input class="filter-checkbox" type="checkbox" style="width: calc(100% - 1.5em);height: 40px;">'+fa+
|
||||||
|
'<ul class="sub-items">' +
|
||||||
|
member_cards +
|
||||||
|
'</ul></div>' +
|
||||||
|
'</li>')
|
||||||
|
};
|
||||||
|
};
|
||||||
|
function select_subscribers(){
|
||||||
|
window.selected_subscriber_ids = [];
|
||||||
|
var subscriber_cards = $('#member-filter [name="subscriber_ids[]"]:checked').map(function(i, subscriber){
|
||||||
|
window.selected_subscriber_ids.push(subscriber.value);
|
||||||
|
return $(subscriber).parent().parent().prop("outerHTML").replace('check-item active','check-item');
|
||||||
|
}).toArray().join('');
|
||||||
|
$('#members_field').html('<ul id="card-list-managers" class="checkbox-card clearfix">'+subscriber_cards+'</ul>');
|
||||||
|
$('#members_field #card-list-managers .check-item').removeClass('hide');
|
||||||
|
if(subscriber_cards != ""){
|
||||||
|
$('#members_field').css('display','block');
|
||||||
|
$('#edit_member_hint').css('display','none');
|
||||||
|
}else{
|
||||||
|
$('#members_field').css('display','none');
|
||||||
|
$('#edit_member_hint').css('display','block');
|
||||||
|
}
|
||||||
|
$('#members_field').change();
|
||||||
|
$("#member-filter").modal('hide');
|
||||||
|
}
|
||||||
|
$(document).ready(function(){
|
||||||
|
$('#subscribers_form [type="submit"]').click(select_subscribers);
|
||||||
|
if(window.selected_subscriber_ids){
|
||||||
|
window.selected_subscriber_ids.forEach(function(v){
|
||||||
|
var $v = $(`#member-filter input[value="${v}"]`);
|
||||||
|
$v.prop("checked", true);
|
||||||
|
$v.parent().parent().addClass('active');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
$('.search_emails').off('input').on('input',function(){
|
||||||
|
var name = $(this).val();
|
||||||
|
var $check_items = $(this).parent().find('.check-item');
|
||||||
|
$check_items.each(function(i,item){
|
||||||
|
if( $(item).find('.subscriber_email').text().search(name) == -1){
|
||||||
|
$(item).addClass('hide');
|
||||||
|
}else{
|
||||||
|
$(item).removeClass('hide');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,339 @@
|
||||||
|
<%= stylesheet_link_tag "member_select" %>
|
||||||
|
<%= stylesheet_link_tag "lib/checkbox-card" %>
|
||||||
|
<div class="mini-layout-body span10">
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="tab-pane fade in active" id="subscribers_block">
|
||||||
|
<div class="tab-pane-head">
|
||||||
|
<h4><%= t('e_paper.batch_delete_subscribers') %></h4>
|
||||||
|
</div>
|
||||||
|
<ul id="card-list-members" class="checkbox-card clearfix">
|
||||||
|
<fieldset style="background-color: white;border: 0.125em solid #666;font-family: cursive,serif;">
|
||||||
|
<%= form_tag admin_e_paper_subscribers_delete_subscribers_path , :id=>'members_form' do %>
|
||||||
|
<div id="members_field" style="display: none;margin-left: 1.5em;margin-left: 1.5em;"></div>
|
||||||
|
<p id="edit_member_hint" aligin="center" style="font-size: 1.5em;padding: 2em;text-align: center;"><%= t("e_paper.delete_subscribers_hint") %></p>
|
||||||
|
<input id="submit-type" name="type" type="hidden" value="">
|
||||||
|
<% end %>
|
||||||
|
</fieldset>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- footer -->
|
||||||
|
<div class="bottomnav clearfix">
|
||||||
|
<div class="action pull-right">
|
||||||
|
<div class="btn-group dropup">
|
||||||
|
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
|
||||||
|
<%= t("select") %>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#" id="select_all"><i class="icon-ok"></i> <%= t("select_all") %></a></li>
|
||||||
|
<li><a href="#" id="deselect_all"><i class="icon-remove"></i> <%= t("de_select_all") %></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary select_member_modal" href="#" type="button">
|
||||||
|
<i class="icons-plus"></i>
|
||||||
|
<%=t(:add)%>
|
||||||
|
</button>
|
||||||
|
<button class="btn" id="remove_subscribers" style="display: none;"><i class="icon-trash"></i> <%=t('site.edit_members.delete_from_choice') %></button>
|
||||||
|
<button class="btn btn-danger" id="remove_subscribers_forever" style="display: none;"><i class="icon-trash"></i> <%=t('e_paper.delete_subscribers') %></button>
|
||||||
|
<!-- <button class="btn" id="edit_members" style="display: none;"><i class="icon-trash"></i> <%=t('site.edit_members.edit_members') %></button> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% if @thread %>
|
||||||
|
<div id="threadModal" class="modal hide fade in" tabindex="-1" role="dialog" aria-labelledby="threadModal" aria-hidden="false">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 id="threadModal"><%=t("site.edit_members.#{@thread.key}")%></h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<%= @thread.status[:finish_percent] %> % finished
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn" id="modal-close-btn" style="width: 4em;" data-dismiss="modal" aria-hidden="true"><%=t('close')%></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<div id='select_member_modal'></div>
|
||||||
|
<script src="/assets/lib/jquery-ui-1.12.1/jquery-ui.min.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
/* 修正bootstap.js和jquery-ui.js間的衝突,使tab按鈕能正常運作 */
|
||||||
|
var Button = function (element, options) {
|
||||||
|
this.$element = $(element)
|
||||||
|
this.options = $.extend({}, $.fn.button.defaults, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button.prototype.setState = function (state) {
|
||||||
|
var d = 'disabled'
|
||||||
|
, $el = this.$element
|
||||||
|
, data = $el.data()
|
||||||
|
, val = $el.is('input') ? 'val' : 'html'
|
||||||
|
|
||||||
|
state = state + 'Text'
|
||||||
|
data.resetText || $el.data('resetText', $el[val]())
|
||||||
|
|
||||||
|
$el[val](data[state] || this.options[state])
|
||||||
|
|
||||||
|
// push to event loop to allow forms to submit
|
||||||
|
setTimeout(function () {
|
||||||
|
state == 'loadingText' ?
|
||||||
|
$el.addClass(d).attr(d, d) :
|
||||||
|
$el.removeClass(d).removeAttr(d)
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button.prototype.toggle = function () {
|
||||||
|
var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
|
||||||
|
|
||||||
|
$parent && $parent
|
||||||
|
.find('.active')
|
||||||
|
.removeClass('active')
|
||||||
|
|
||||||
|
this.$element.toggleClass('active')
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BUTTON PLUGIN DEFINITION
|
||||||
|
* ======================== */
|
||||||
|
|
||||||
|
var old = $.fn.button
|
||||||
|
|
||||||
|
$.fn.button = function (option) {
|
||||||
|
return this.each(function () {
|
||||||
|
var $this = $(this)
|
||||||
|
, data = $this.data('button')
|
||||||
|
, options = typeof option == 'object' && option
|
||||||
|
if (!data) $this.data('button', (data = new Button(this, options)))
|
||||||
|
if (option == 'toggle') data.toggle()
|
||||||
|
else if (option) data.setState(option)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/* 修正bootstap.js和jquery-ui.js間的衝突,使tab按鈕能正常運作 */
|
||||||
|
</script>
|
||||||
|
<link rel="stylesheet" href="/assets/lib/jquery-ui-1.12.1/jquery-ui.min.css">
|
||||||
|
<script type="text/javascript">
|
||||||
|
if( Array.prototype.delete == undefined ){
|
||||||
|
Array.prototype.delete = function(v){
|
||||||
|
var idx = this.indexOf(v);
|
||||||
|
if(idx != -1){
|
||||||
|
return this.splice(idx, 1)[0];
|
||||||
|
}else{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function double_confirm_message(message){
|
||||||
|
if(window.confirm(message)){
|
||||||
|
if(window.confirm(message)){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
$(document).ready(function(){
|
||||||
|
$(document).on('click','.modal-body .tab-content .check-item',function(){
|
||||||
|
if($(this).hasClass("active"))
|
||||||
|
$(this).removeClass("active");
|
||||||
|
else
|
||||||
|
$(this).addClass("active");
|
||||||
|
});
|
||||||
|
$(document).on('click',"#select_all",function(){
|
||||||
|
$('#members_field').find(".check-item").addClass("active");
|
||||||
|
$('#members_field').find(".check-item input[type=checkbox]").prop("checked","checked");
|
||||||
|
$(".bottomnav .dropup").removeClass("open");
|
||||||
|
if($('#members_field .filter-item').length != 0)
|
||||||
|
$('#remove_subscribers').css('display','inline-block');
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$(document).on('click',"#deselect_all",function(){
|
||||||
|
$('#members_field').find(".check-item").removeClass("active");
|
||||||
|
$('#members_field').find(".check-item input[type=checkbox]").removeAttr("checked");
|
||||||
|
$(".bottomnav .dropup").removeClass("open");
|
||||||
|
$('#remove_subscribers').css('display','none');
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$(document).on('click',".select_all_modal",function(){
|
||||||
|
$('#select_member_modal .tab-pane.active').find('.check-item:not(.hide)').addClass("active");
|
||||||
|
$('#select_member_modal .tab-pane.active').find('.check-item:not(.hide) input[type=checkbox]').prop("checked","checked");
|
||||||
|
$(".modal-body .dropup").removeClass("open");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$(document).on('click',".deselect_all_modal",function(){
|
||||||
|
$('#select_member_modal .tab-pane.active').find('.check-item:not(.hide)').removeClass("active");
|
||||||
|
$('#select_member_modal .tab-pane.active').find('.check-item:not(.hide) input[type=checkbox]').prop("checked","");
|
||||||
|
$(".modal-body .dropup").removeClass("open");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$(document).on('click',".select_member_modal",function () {
|
||||||
|
$.get("<%= admin_e_paper_subscribers_get_subscribers_modal_path %>").done(function(data){
|
||||||
|
$("#select_member_modal").html(data);
|
||||||
|
$("#member-filter").modal('show');
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$('#remove_subscribers').click(function(){
|
||||||
|
var $delete_items = $('#members_field .check-item.active');
|
||||||
|
var delete_count = $delete_items.length;
|
||||||
|
for(var i = 0;i < delete_count;i++){
|
||||||
|
window.selected_subscriber_ids.delete($delete_items.eq(i).find('input').val());
|
||||||
|
$delete_items.eq(i).remove();
|
||||||
|
};
|
||||||
|
if($('#members_field .check-item').length == 0)
|
||||||
|
$('#edit_member_hint').css('display','block');
|
||||||
|
$(this).css('display','none');
|
||||||
|
if($('#members_field .check-item').length != 0){
|
||||||
|
$('#remove_subscribers_forever').css('display','inline-block');
|
||||||
|
$('#edit_members').css('display','inline-block');
|
||||||
|
}else{
|
||||||
|
$('#remove_subscribers_forever').css('display','none');
|
||||||
|
$('#edit_members').css('display','none');
|
||||||
|
};
|
||||||
|
});
|
||||||
|
$('#members_field').change(function(){
|
||||||
|
if($('#members_field .check-item').length != 0){
|
||||||
|
$('#remove_subscribers_forever').css('display','inline-block');
|
||||||
|
$('#edit_members').css('display','inline-block');
|
||||||
|
}else{
|
||||||
|
$('#remove_subscribers_forever').css('display','none');
|
||||||
|
$('#edit_members').css('display','none');
|
||||||
|
};
|
||||||
|
$('#members_field .check-item').off('click').on('click',function(){
|
||||||
|
$el = $(this).parent().parent();
|
||||||
|
if($el.hasClass("active")){
|
||||||
|
$el.removeClass('active');
|
||||||
|
if($('#members_field .check-item.active').length != 0)
|
||||||
|
$('#remove_subscribers').css('display','inline-block');
|
||||||
|
else
|
||||||
|
$('#remove_subscribers').css('display','none');
|
||||||
|
}else{
|
||||||
|
$el.addClass('active');
|
||||||
|
$('#remove_subscribers').css('display','inline-block');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$('#members_field .check-item').off('click').on('click',function(){
|
||||||
|
if($(this).hasClass("active"))
|
||||||
|
$(this).removeClass("active");
|
||||||
|
else
|
||||||
|
$(this).addClass("active");
|
||||||
|
if($('#members_field .check-item.active').length != 0)
|
||||||
|
$('#remove_subscribers').css('display','inline-block');
|
||||||
|
else
|
||||||
|
$('#remove_subscribers').css('display','none');
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$('.fa-caret-down').off('click').on('click',function(){
|
||||||
|
if($(this).parent().hasClass('open'))
|
||||||
|
$(this).parent().removeClass("open");
|
||||||
|
else
|
||||||
|
$(this).parent().addClass("open");
|
||||||
|
})
|
||||||
|
$('#remove_subscribers_forever').off('click').on('click',function(){
|
||||||
|
var member_cards = '<ul id="card-list-managers" class="checkbox-card clearfix" style="clear: left;">'+$.map($('#members_field .check-item'),function(member_card,i){
|
||||||
|
return member_card.outerHTML;
|
||||||
|
}).join('')+'</ul>';
|
||||||
|
if(double_confirm_message('<%= t('e_paper.delete_subscribers_hint') %>')){
|
||||||
|
$("#members_form").before("<div id='dialog-confirm' title='"+"<%= t('site.edit_members.delete_hint1') %>'>"+
|
||||||
|
"<div style='clear:both;'></div><div><span class='ui-icon ui-icon-alert' style='float:left; margin:0 7px 20px 0;'></span>"+
|
||||||
|
"<%= t('e_paper.delete_subscribers_hint2') %>"+member_cards+"</div>"+
|
||||||
|
"</div>");
|
||||||
|
$( "#dialog-confirm" ).dialog({
|
||||||
|
resizable: true,
|
||||||
|
minHeight: 100,
|
||||||
|
maxHeight: 400,
|
||||||
|
modal: true,
|
||||||
|
buttons: {
|
||||||
|
"<%= t('site.edit_members.confirm') %>": function(){$('#submit-type').val('remove_subscribers_forever');$('#members_form').submit();$( this ).dialog( "close" );},
|
||||||
|
"<%= t('site.edit_members.cancel') %>": function() {
|
||||||
|
$( this ).dialog( "close" );
|
||||||
|
$( this ).remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#edit_members').off('click').on('click',function(){
|
||||||
|
$('#submit-type').val('select_edit_members');
|
||||||
|
$('#members_form').submit();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
function update_thread(){
|
||||||
|
$.post("<%=admin_threads_get_status_path%>",{"id": "<%=params[:thread_id]%>"}).done(function(data){
|
||||||
|
var finish_percent = data["finish_percent"];
|
||||||
|
var is_finish = (data["status"] == "finish" || data["status"] == "error");
|
||||||
|
if(finish_percent){
|
||||||
|
$("#threadModal .modal-body").text(finish_percent + " % finished")
|
||||||
|
}
|
||||||
|
if(!is_finish){
|
||||||
|
window.time_out_id = window.setTimeout(update_thread, 1000);
|
||||||
|
}else{
|
||||||
|
if(window.time_out_id)
|
||||||
|
window.clearTimeout(window.time_out_id);
|
||||||
|
window.setTimeout(function(){
|
||||||
|
$("#threadModal").modal("hide");
|
||||||
|
alert(data["status"]);
|
||||||
|
}, 3000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if($("#threadModal").length != 0){
|
||||||
|
$("#threadModal").modal("show");
|
||||||
|
window.time_out_id = window.setTimeout(update_thread, 1000);
|
||||||
|
}
|
||||||
|
$(document).on('click','.modal-backdrop',function(){
|
||||||
|
$('.modal').modal('hide');
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style type="text/css">
|
||||||
|
.checkbox-card li:focus-within span{
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.fa-caret-down:before {
|
||||||
|
content: "\f078";
|
||||||
|
}
|
||||||
|
.sub-items{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.open .sub-items{
|
||||||
|
display: block;
|
||||||
|
margin: 0 0.5em;
|
||||||
|
}
|
||||||
|
.selected_role .selected_member:hover{
|
||||||
|
background-color: #cccccc;
|
||||||
|
}
|
||||||
|
.selected_role .selected_member{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
li.selected_role:hover{
|
||||||
|
background-color: #696969;
|
||||||
|
}
|
||||||
|
.selected:hover{
|
||||||
|
background-color: #0088cc;
|
||||||
|
}
|
||||||
|
.selected{
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
#remove_subscribers{
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
#edit_members{
|
||||||
|
background: green;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
#members_field .checkbox-card li:hover label span.user-name {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
#members_field .checkbox-card li:hover > label > span.user-name {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,25 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
wb = xlsx_package.workbook
|
||||||
|
|
||||||
|
wb.add_worksheet(name: "Subscribe") do |sheet|
|
||||||
|
|
||||||
|
heading = sheet.styles.add_style(:b => true, :locked => true)
|
||||||
|
body = sheet.styles.add_style(:font_name => '微軟正黑體')
|
||||||
|
row = []
|
||||||
|
row << t('email')
|
||||||
|
row << t('language') + " , ex: #{I18n.available_locales.map{|l| l.to_s}.join(', ')}"
|
||||||
|
|
||||||
|
sheet.add_row row, :style => heading
|
||||||
|
end
|
||||||
|
|
||||||
|
wb.add_worksheet(name: "Unsubscribe") do |sheet|
|
||||||
|
|
||||||
|
heading = sheet.styles.add_style(:b => true, :locked => true)
|
||||||
|
body = sheet.styles.add_style(:font_name => '微軟正黑體')
|
||||||
|
row = []
|
||||||
|
row << t('email')
|
||||||
|
row << t('language') + " , ex: #{I18n.available_locales.map{|l| l.to_s}.join(', ')}"
|
||||||
|
|
||||||
|
sheet.add_row row, :style => heading
|
||||||
|
end
|
|
@ -0,0 +1,39 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
wb = xlsx_package.workbook
|
||||||
|
|
||||||
|
wb.add_worksheet(name: "Subscribe") do |sheet|
|
||||||
|
|
||||||
|
heading = sheet.styles.add_style(:b => true, :locked => true)
|
||||||
|
body = sheet.styles.add_style(:font_name => '微軟正黑體')
|
||||||
|
row = []
|
||||||
|
row << t('email')
|
||||||
|
row << t('language')
|
||||||
|
|
||||||
|
sheet.add_row row, :style => heading
|
||||||
|
|
||||||
|
@subscribers.each do |subscriber|
|
||||||
|
row = []
|
||||||
|
row << subscriber.email
|
||||||
|
row << subscriber.language
|
||||||
|
sheet.add_row row, :style => body, :types => [:string,:string]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
wb.add_worksheet(name: "Unsubscribe") do |sheet|
|
||||||
|
|
||||||
|
heading = sheet.styles.add_style(:b => true, :locked => true)
|
||||||
|
body = sheet.styles.add_style(:font_name => '微軟正黑體')
|
||||||
|
row = []
|
||||||
|
row << t('email')
|
||||||
|
row << t('language')
|
||||||
|
|
||||||
|
sheet.add_row row, :style => heading
|
||||||
|
|
||||||
|
@unsubscribers.each do |subscriber|
|
||||||
|
row = []
|
||||||
|
row << subscriber.email
|
||||||
|
row << subscriber.language
|
||||||
|
sheet.add_row row, :style => body, :types => [:string,:string]
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,3 +1,53 @@
|
||||||
|
<style>
|
||||||
|
.pull-right .upload-box {
|
||||||
|
background: #fff none repeat scroll 0 0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 70px;
|
||||||
|
left: auto;
|
||||||
|
min-width: 350px;
|
||||||
|
padding: 10px;
|
||||||
|
position: absolute;
|
||||||
|
right: -1px;
|
||||||
|
top: -75px;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu {
|
||||||
|
top: auto;
|
||||||
|
bottom: 100%;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
.open > .dropdown-menu {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.dropdown-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
display: none;
|
||||||
|
float: left;
|
||||||
|
min-width: 160px;
|
||||||
|
padding: 5px 0;
|
||||||
|
margin: 2px 0 0;
|
||||||
|
list-style: none;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||||
|
*border-right-width: 2px;
|
||||||
|
*border-bottom-width: 2px;
|
||||||
|
-webkit-border-radius: 6px;
|
||||||
|
-moz-border-radius: 6px;
|
||||||
|
border-radius: 6px;
|
||||||
|
-webkit-box-shadow: 0 5px 10px rgb(0 0 0 / 20%);
|
||||||
|
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||||
|
box-shadow: 0 5px 10px rgb(0 0 0 / 20%);
|
||||||
|
-webkit-background-clip: padding-box;
|
||||||
|
-moz-background-clip: padding;
|
||||||
|
background-clip: padding-box;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<%= render_filter @filter_fields, "index_table" %>
|
<%= render_filter @filter_fields, "index_table" %>
|
||||||
<div id="index_table">
|
<div id="index_table">
|
||||||
<%= render 'index'%>
|
<%= render 'index'%>
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
en:
|
en:
|
||||||
module_name:
|
module_name:
|
||||||
e_paper: "ePaper"
|
e_paper: "ePaper"
|
||||||
|
restful_actions:
|
||||||
|
batch_delete_subscribers: "Batch Delete Subscribers"
|
||||||
e_paper:
|
e_paper:
|
||||||
|
delete_subscribers_hint2: "Delete Subscribers below forever."
|
||||||
|
delete_subscribers_hint1: "Do you realy want to delete Subscribers you added forever?"
|
||||||
|
delete_subscribers_hint: "Click 『Add』 button to select Subscribers"
|
||||||
|
delete_subscribers: "Delete Subscribers"
|
||||||
|
batch_delete_subscribers: "Batch Delete Subscribers"
|
||||||
|
import: "Import"
|
||||||
|
export: "Export"
|
||||||
get_invalid_emails: get invalid email
|
get_invalid_emails: get invalid email
|
||||||
get_failed_emails: get sended-failed emails
|
get_failed_emails: get sended-failed emails
|
||||||
e_paper: "ePaper"
|
e_paper: "ePaper"
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
zh_tw:
|
zh_tw:
|
||||||
module_name:
|
module_name:
|
||||||
e_paper: 電子報
|
e_paper: 電子報
|
||||||
|
restful_actions:
|
||||||
|
batch_delete_subscribers: "批次刪除訂閱者"
|
||||||
e_paper:
|
e_paper:
|
||||||
|
delete_subscribers_hint2: "永久刪除以下訂閱者"
|
||||||
|
delete_subscribers_hint1: "您確定真的要永久刪除所選的訂閱者嗎?"
|
||||||
|
delete_subscribers_hint: "點選『新增』按鈕選擇訂閱者"
|
||||||
|
delete_subscribers: "刪除訂閱者"
|
||||||
|
batch_delete_subscribers: "批次刪除訂閱者"
|
||||||
|
import: "匯入"
|
||||||
|
export: "匯出"
|
||||||
get_invalid_emails: 顯示格式錯誤的email
|
get_invalid_emails: 顯示格式錯誤的email
|
||||||
get_failed_emails: 顯示寄送失敗的email
|
get_failed_emails: 顯示寄送失敗的email
|
||||||
e_paper: "電子報"
|
e_paper: "電子報"
|
||||||
|
|
|
@ -12,6 +12,12 @@ Rails.application.routes.draw do
|
||||||
get "get_invalid_emails"
|
get "get_invalid_emails"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
get 'e_paper_subscribers/export_excel', to: 'e_paper_subscribers#export_excel'
|
||||||
|
get 'e_paper_subscribers/download_excel_format', to: 'e_paper_subscribers#download_excel_format'
|
||||||
|
post 'e_paper_subscribers/import_from_excel', to: 'e_paper_subscribers#import_from_excel'
|
||||||
|
get 'e_paper_subscribers/get_subscribers_modal', to: 'e_paper_subscribers#get_subscribers_modal'
|
||||||
|
get 'e_paper_subscribers/batch_delete_subscribers', to: 'e_paper_subscribers#batch_delete_subscribers'
|
||||||
|
post 'e_paper_subscribers/delete_subscribers', to: 'e_paper_subscribers#delete_subscribers'
|
||||||
resources :e_paper_subscribers
|
resources :e_paper_subscribers
|
||||||
resources :e_papers do
|
resources :e_papers do
|
||||||
member do
|
member do
|
||||||
|
|
|
@ -65,9 +65,14 @@ module EPaper
|
||||||
:priority=>6,
|
:priority=>6,
|
||||||
:active_for_action=>{'admin/e_paper_subscribers'=>'index'},
|
:active_for_action=>{'admin/e_paper_subscribers'=>'index'},
|
||||||
:available_for => 'managers'
|
:available_for => 'managers'
|
||||||
|
context_link 'e_paper.batch_delete_subscribers',
|
||||||
|
:link_path=>"admin_e_paper_subscribers_batch_delete_subscribers_path" ,
|
||||||
|
:priority=>7,
|
||||||
|
:active_for_action=>{'admin/e_paper_subscribers'=>'batch_delete_subscribers'},
|
||||||
|
:available_for => 'managers'
|
||||||
context_link 'e_paper.instructions',
|
context_link 'e_paper.instructions',
|
||||||
:link_path=>"instructions_admin_e_papers_path" ,
|
:link_path=>"instructions_admin_e_papers_path" ,
|
||||||
:priority=>7,
|
:priority=>8,
|
||||||
:active_for_action=>{'admin/e_paper'=>'instructions'},
|
:active_for_action=>{'admin/e_paper'=>'instructions'},
|
||||||
:available_for => 'users'
|
:available_for => 'users'
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue