MT#5083 Implement sendfax in ngcp-panel.

agranig/pbxapi
Andreas Granig 12 years ago
parent 75fccd3920
commit b88d36bdf0

@ -14,6 +14,7 @@ use NGCP::Panel::Utils::Preferences;
use NGCP::Panel::Utils::Message;
use NGCP::Panel::Utils::DateTime;
use NGCP::Panel::Utils::Sems;
use NGCP::Panel::Utils::Hylafax;
use NGCP::Panel::Form::Subscriber;
use NGCP::Panel::Form::SubscriberEdit;
use NGCP::Panel::Form::Customer::PbxExtensionSubscriberEdit;
@ -41,6 +42,7 @@ use NGCP::Panel::Form::Faxserver::Active;
use NGCP::Panel::Form::Faxserver::SendStatus;
use NGCP::Panel::Form::Faxserver::SendCopy;
use NGCP::Panel::Form::Faxserver::Destination;
use NGCP::Panel::Form::Subscriber::Webfax;
use NGCP::Panel::Utils::XMLDispatcher;
use UUID;
@ -294,8 +296,103 @@ sub base :Chained('sub_list') :PathPart('') :CaptureArgs(1) {
{ name => "choice", search => 1, title => $c->loc('Slot') },
{ name => "destination", search => 1, title => $c->loc('Destination') },
]);
$c->stash->{fax_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [
{ name => "id", search => 1, title => $c->loc('#') },
{ name => "the_timestamp", search_from_epoch => 1, search_to_epoch => 1, title => $c->loc('Timestamp') },
{ name => "status", search => 1, title => $c->loc('Status') },
{ name => "duration", search => 1, title => $c->loc('Duration') },
{ name => "direction", search => 1, title => $c->loc('Direction') },
{ name => "peer_number", search => 1, title => $c->loc('Peer Number') },
{ name => "pages", search => 1, title => $c->loc('Pages') },
]);
}
sub webfax :Chained('base') :PathPart('webfax') :Args(0) {
my ($self, $c) = @_;
$c->stash(
template => 'subscriber/webfax.tt',
);
}
sub webfax_send :Chained('base') :PathPart('webfax/send') :Args(0) {
my ($self, $c) = @_;
my $subscriber = $c->stash->{subscriber};
my $form = NGCP::Panel::Form::Subscriber::Webfax->new;
my $posted = ($c->request->method eq 'POST');
my $params = {};
if($posted) {
$c->req->params->{faxfile} = $c->req->upload('faxfile');
}
$form->process(
posted => $posted,
params => $c->req->params,
);
NGCP::Panel::Utils::Navigation::check_form_buttons(
c => $c,
form => $form,
fields => {},
back_uri => $c->uri_for_action('/subscriber/webfax', $c->req->captures),
);
if($posted && $form->validated) {
try {
if(defined $form->params->{faxfile}) {
NGCP::Panel::Utils::Hylafax::send_fax(
c => $c,
subscriber => $subscriber,
destination => $form->params->{destination},
#resolution => 'low', # opt (low, medium, extended)
#notify => 'someone@example.org', # TODO: handle in send_fax, read from prefs!
#coverpage => 1,
upload => $form->params->{faxfile},
);
} else {
NGCP::Panel::Utils::Hylafax::send_fax(
c => $c,
subscriber => $subscriber,
destination => $form->params->{destination},
#resolution => 'low', # opt (low, medium, extended)
#notify => 'someone@example.org', # TODO: handle in send_fax, read from prefs!
#coverpage => 1,
data => $form->params->{data},
);
}
} catch($e) {
NGCP::Panel::Utils::Message->error(
c => $c,
error => "failed to send fax: $e",
desc => $c->loc('Internal error while sending fax'),
);
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/subscriber/webfax', $c->req->captures));
return;
}
}
$c->stash(
template => 'subscriber/webfax.tt',
form => $form,
create_flag => 1,
);
}
sub webfax_ajax :Chained('base') :PathPart('webfax/ajax') :Args(0) {
my ($self, $c) = @_;
my $s = $c->stash->{subscriber}->provisioning_voip_subscriber;
my $fax_rs = $c->model('DB')->resultset('fax_journal')->search({
subscriber_id => $s->id,
});
NGCP::Panel::Utils::Datatables::process($c, $fax_rs, $c->stash->{fax_dt_columns});
$c->detach( $c->view("JSON") );
}
sub webphone :Chained('base') :PathPart('webphone') :Args(0) {
my ($self, $c) = @_;

@ -0,0 +1,76 @@
package NGCP::Panel::Form::Subscriber::Webfax;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler';
use Moose::Util::TypeConstraints;
use HTML::FormHandler::Widget::Block::Bootstrap;
has '+widget_wrapper' => ( default => 'Bootstrap' );
has '+enctype' => ( default => 'multipart/form-data');
has_field 'submitid' => ( type => 'Hidden' );
sub build_render_list {[qw/submitid fields actions/]}
sub build_form_element_class {[qw(form-horizontal)]}
has_field 'destination' => (
type => 'Text',
label => 'Destination Number',
required => 1,
element_attr => {
rel => ['tooltip'],
title => ['The number to send the fax to']
},
);
has_field 'data' => (
type => 'TextArea',
label => 'Content',
cols => 200,
rows => 10,
maxlength => '1048576', # 1MB
element_class => [qw/ngcp-autoconf-area/],
);
has_field 'faxfile' => (
type => 'Upload',
max_size => 67108864,
label => 'or File',
element_attr => {
rel => ['tooltip'],
title => ['Supported File Types are TXT, PDF, PS, TIFF']
},
);
has_field 'save' => (
type => 'Submit',
value => 'Send',
element_class => [qw/btn btn-primary/],
label => '',
);
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/destination data faxfile/],
);
has_block 'actions' => (
tag => 'div',
class => [qw/modal-footer/],
render_list => [qw/save/],
);
sub validate {
my $self = shift;
my $data = $self->field('data')->value;
my $upload = $self->field('faxfile')->value;
use Data::Printer; print ">>>>>>>>>>>>>>>>>>>>>> upload\n"; p $data; p $upload; p $self->fields;
unless($data || $upload) {
$self->field('faxfile')->add_error("You need to specify a file to fax, if no text is entered in the content field");
}
}
1;
# vim: set tabstop=4 expandtab:

@ -0,0 +1,89 @@
package NGCP::Panel::Utils::Hylafax;
use Sipwise::Base;
use File::Temp qw/tempfile/;
use TryCatch;
use Data::Dumper;
sub send_fax {
my (%args) = @_;
my $c = $args{c};
my $subscriber = $args{subscriber};
my $prov_subscriber = $subscriber->provisioning_voip_subscriber;
my $sendfax = $c->config->{faxserver}->{sendfax} // '/usr/bin/sendfax';
my @sendfax_args = ();
my $sender = 'webfax';
my $number;
if($subscriber->primary_number) {
$number = $subscriber->primary_number->cc .
($subscriber->primary_number->ac // '').
$subscriber->primary_number->sn;
} else {
$number = $sender;
}
if($prov_subscriber->voip_fax_preference) {
$sender = $prov_subscriber->voip_fax_preference->name;
if($prov_subscriber->voip_fax_preference->password) {
push @sendfax_args, '-o '.$number.':'.$prov_subscriber->voip_fax_preference->password;
} else {
push @sendfax_args, '-o '.$number;
}
} else {
push @sendfax_args, '-o '.$number;
}
push @sendfax_args, '-h '.($c->config->{faxserver}->{ip} // '127.0.0.1');
if($args{notify}) {
push @sendfax_args, '-D';
push @sendfax_args, "-f '$sender <$args{notify}>'";
} else {
push @sendfax_args, "-f '$sender'";
}
unless($args{coverpage}) {
push @sendfax_args, '-n';
}
if($args{resolution}) {
if($args{resolution} eq 'low') {
push @sendfax_args, '-l';
} elsif($args{resolution} eq 'medium') {
push @sendfax_args, '-m';
} elsif($args{resolution} eq 'extended') {
push @sendfax_args, '-G';
}
}
push @sendfax_args, '-d '.$args{destination};
my ($fh, $filename);
if($args{data}) {
($fh, $filename) = tempfile;
unless(print $fh $args{data}) {
my $err = $!;
close $fh;
unlink $filename;
die $c->loc("Failed to write fax data to temporary file: [_1]", $err);
}
close $fh;
} else {
$filename = eval { $args{upload}->tempname };
}
push @sendfax_args, $filename;
my $sa = join(' ', @sendfax_args);
my $output = `$sendfax $sa 2>&1`;
my $exit = $?;
unlink $filename;
if($exit ne '0') {
chomp $output;
die $output."\n";
}
}
1;
# vim: set tabstop=4 expandtab:

@ -28,6 +28,11 @@ log4perl.appender.Default.layout.ConversionPattern=%d{ISO8601} [%p] [%F +%L] %m{
cloudpbx 1
</features>
<faxserver>
sendfax /usr/bin/sendfax
ip 127.0.0.1
</faxserver>
<fees_csv>
element_order source
element_order destination

@ -26,6 +26,7 @@ $.extend( $.fn.dataTableExt.oStdClasses, {
} );
$(document).ready(function() {
var date_search_rendered = 0;
var [% helper.id_from_name %]_table = $('#[% helper.id_from_name %]_table')
.dataTable( {
"sDom": "<'row-fluid ngcp_dt_top_elements'lf<r>>t<'row-fluid'<'pull-left'i><'pull-right'p>>",
@ -114,6 +115,43 @@ $(document).ready(function() {
function() { $(this).find('.sw_actions').css('visibility','visible'); },
function() { $(this).find('.sw_actions').css('visibility','hidden'); }
);
if(date_search_rendered) return;
date_search_rendered = 1;
[% has_from = 0; has_to = 0; -%]
[% FOR col IN helper.dt_columns -%]
[% IF col.search_from_epoch && !has_from -%]
var f = '<label>From Date: <input type="text" id="[% helper.id_from_name %]_datepicker_start" class="ngcp-datepicker" rel="tooltip" data-original-title="YYYY-MM-DD"/></label>';
$('#[% helper.id_from_name %]_table_filter').prepend(f);
$('#[% helper.id_from_name %]_datepicker_start').datepicker({
"dateFormat": "yy-mm-dd",
"onSelect": function(date) {
[% helper.id_from_name %]_table.fnFilter(date, 0);
}
}).keyup( function () {
[% helper.id_from_name %]_table.fnFilter(this.value, 0);
});
[% has_from = 1 -%]
[% END -%]
[% IF col.search_to_epoch && !has_to -%]
var t = '<label>To Date: <input type="text" id="[% helper.id_from_name %]_datepicker_end" class="ngcp-datepicker" rel="tooltip" data-original-title="YYYY-MM-DD"/></label>';
if($('#[% helper.id_from_name %]_datepicker_start').length > 0) {
$('#[% helper.id_from_name %]_datepicker_start').parent().after(t);
} else {
$('#[% helper.id_from_name %]_table_filter').prepend(t);
}
$('#[% helper.id_from_name %]_datepicker_end').datepicker({
"dateFormat": "yy-mm-dd",
"onSelect": function(date) {
[% helper.id_from_name %]_table.fnFilter(date, 1);
}
}).keyup( function () {
[% helper.id_from_name %]_table.fnFilter(this.value, 1);
});
[% has_to = 1-%]
[% END -%]
[% END %]
},
"fnRowCallback": function(nRow, aData, iDisplayIndex) {
nRow.className = "sw_action_row";
@ -121,40 +159,6 @@ $(document).ready(function() {
},
} );
[% has_from = 0; has_to = 0; -%]
[% FOR col IN helper.dt_columns -%]
[% IF col.search_from_epoch && !has_from -%]
var f = '<label>From Date: <input type="text" id="[% helper.id_from_name %]_datepicker_start" class="ngcp-datepicker" rel="tooltip" data-original-title="YYYY-MM-DD"/></label>';
$('#[% helper.id_from_name %]_table_filter').prepend(f);
$('#[% helper.id_from_name %]_datepicker_start').datepicker({
"dateFormat": "yy-mm-dd",
"onSelect": function(date) {
[% helper.id_from_name %]_table.fnFilter(date, 0);
}
}).keyup( function () {
[% helper.id_from_name %]_table.fnFilter(this.value, 0);
});
[% has_from = 1 -%]
[% END -%]
[% IF col.search_to_epoch && !has_to -%]
var t = '<label>To Date: <input type="text" id="[% helper.id_from_name %]_datepicker_end" class="ngcp-datepicker" rel="tooltip" data-original-title="YYYY-MM-DD"/></label>';
if($('#[% helper.id_from_name %]_datepicker_start').length > 0) {
$('#[% helper.id_from_name %]_datepicker_start').parent().after(t);
} else {
$('#[% helper.id_from_name %]_table_filter').prepend(t);
}
$('#[% helper.id_from_name %]_datepicker_end').datepicker({
"dateFormat": "yy-mm-dd",
"onSelect": function(date) {
[% helper.id_from_name %]_table.fnFilter(date, 1);
}
}).keyup( function () {
[% helper.id_from_name %]_table.fnFilter(this.value, 1);
});
[% has_to = 1-%]
[% END -%]
[% END %]
} );
</script>

@ -0,0 +1,19 @@
[% site_config.title = c.loc('Fax Journal for [_1]@[_2]', subscriber.username, subscriber.domain.domain) -%]
[%
helper.name = c.loc('Fax');
helper.dt_columns = fax_dt_columns;
helper.column_sort = 'the_timestamp';
helper.form_object = form;
helper.create_flag = create_flag;
helper.ajax_uri = c.uri_for_action('/subscriber/webfax_ajax', [c.req.captures.0]);
helper.messages = messages;
helper.top_buttons = [
{ name = c.loc('Send Fax'), uri = c.uri_for_action('/subscriber/webfax_send', [ subscriber.id ]), icon = 'icon-print' },
];
PROCESS 'helpers/datatables.tt';
%]
[% # vim: set tabstop=4 syntax=html expandtab: -%]
Loading…
Cancel
Save