TT#64653 Add thumbnail support to admin panel

Change-Id: Ibf4a09ad8ad0d67fc2264891c80a71b9f86536f8
changes/03/32603/9
Andreas Granig 7 years ago
parent 86faa0fab1
commit 536935f754

@ -23,7 +23,7 @@ sub query_params {
return [
{
param => 'type',
description => 'Either "front" (default) or "mac" to download one or the other.',
description => 'Either "front" (default), "front_thumb" or "mac" to download one or the other.',
query => {
# handled directly in role
first => sub {},

@ -27,6 +27,13 @@ sub get_item_binary_data{
if($type eq 'mac') {
$data = $item->mac_image;
$mime_type = $item->mac_image_type;
} elsif($type eq 'front_thumb') {
$data = $item->front_thumbnail;
$mime_type = $item->front_thumbnail_type;
unless (defined $data) {
$data = $item->front_image;
$mime_type = $item->front_image_type;
}
} else {
$data = $item->front_image;
$mime_type = $item->front_image_type;

@ -14,7 +14,7 @@ sub allowed_methods{
__PACKAGE__->set_config({
POST => {
'ContentType' => ['multipart/form-data'],
'Uploads' => [qw/front_image mac_image/],
'Uploads' => [qw/front_image mac_image front_thumbnail/],
},
allowed_roles => {
'Default' => [qw/admin reseller subscriberadmin subscriber/],
@ -22,10 +22,10 @@ __PACKAGE__->set_config({
}
});
# curl -v -X POST --user $USER --insecure -F front_image=@sandbox/spa504g-front.jpg -F mac_image=@sandbox/spa504g-back.jpg -F json='{"reseller_id":1, "vendor":"Cisco", "model":"SPA999", "linerange":[{"name": "Phone Keys", "can_private":true, "can_shared":true, "can_blf":true, "keys":[{"labelpos":"top", "x":5110, "y":5120},{"labelpos":"top", "x":5310, "y":5320}]}]}' https://localhost:4443/api/pbxdevicemodels/
# curl -v -X POST --user $USER --insecure -F front_image=@sandbox/spa504g-front.png -F mac_image=@sandbox/spa504g-back.png -F front_thumbnail=@sandbox/spa504g-front-small.png -F json='{"reseller_id":1, "vendor":"Cisco", "model":"SPA999", "linerange":[{"name": "Phone Keys", "can_private":true, "can_shared":true, "can_blf":true, "keys":[{"labelpos":"top", "x":5110, "y":5120},{"labelpos":"top", "x":5310, "y":5320}]}]}' https://localhost:4443/api/pbxdevicemodels/
sub api_description {
return 'Specifies a model to be set in <a href="#pbxdeviceconfigs">PbxDeviceConfigs</a>. Use a Content-Type "multipart/form-data", provide front_image and mac_image parts with the actual images, and an additional json part with the properties specified below, e.g.: <code>curl -X POST --user $USER -F front_image=@/path/to/front.png -F mac_image=@/path/to/mac.png -F json=\'{"reseller_id":...}\' https://example.org:1443/api/pbxdevicemodels/</code> This resource is read-only to subscriberadmins.';
return 'Specifies a model to be set in <a href="#pbxdeviceconfigs">PbxDeviceConfigs</a>. Use a Content-Type "multipart/form-data", provide front_image, front_thumbnail and mac_image parts with the actual images, and an additional json part with the properties specified below, e.g.: <code>curl -X POST --user $USER -F front_image=@/path/to/front.png -F mac_image=@/path/to/mac.png -F front_thumbnail=@/path/to/front-small.png -F json=\'{"reseller_id":...}\' https://example.org:1443/api/pbxdevicemodels/</code> This resource is read-only to subscriberadmins.';
};
sub query_params {

@ -8,7 +8,7 @@ use parent qw/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::PbxDeviceM
__PACKAGE__->set_config({
PUT => {
'ContentType' => ['multipart/form-data'],
'Uploads' => [qw/front_image mac_image/],
'Uploads' => [qw/front_image mac_image front_thumbnail/],
},
allowed_roles => {
'Default' => [qw/admin reseller subscriberadmin subscriber/],

@ -39,10 +39,11 @@ sub base :Chained('/') :PathPart('device') :CaptureArgs(0) {
}
my $devmod_rs = $c->model('DB')->resultset('autoprov_devices')->search_rs(undef,{
'columns' => [qw/id reseller_id type vendor model front_image_type mac_image_type num_lines bootstrap_method bootstrap_uri extensions_num/,
'columns' => [qw/id reseller_id type vendor model front_image_type mac_image_type front_thumbnail_type num_lines bootstrap_method bootstrap_uri extensions_num/,
{
mac_image_exists => \'mac_image is not null',
front_image_exists => \'front_image is not null',
front_thumbnail_exists => \'front_thumbnail is not null',
}
],
});
@ -157,6 +158,7 @@ sub devmod_ajax :Chained('base') :PathPart('model/ajax') :Args(0) :Does(ACL) :AC
my %data = (
mac_image_exists => $result->get_column('mac_image_exists'),
front_image_exists => $result->get_column('front_image_exists'),
front_thumbnail_exists => $result->get_column('front_thumbnail_exists'),
);
return %data
},
@ -176,6 +178,7 @@ sub extensionmodel_ajax :Chained('base') :PathPart('extensionmodel/ajax') :Args(
my %data = (
mac_image_exists => $result->get_column('mac_image_exists'),
front_image_exists => $result->get_column('front_image_exists'),
front_thumbnail_exists => $result->get_column('front_thumbnail_exists'),
);
return %data
},
@ -199,6 +202,7 @@ sub devmod_create :Chained('base') :PathPart('model/create') :Args(0) :Does(ACL)
if($posted) {
$c->req->params->{front_image} = $c->req->upload('front_image');
$c->req->params->{mac_image} = $c->req->upload('mac_image');
$c->req->params->{front_thumbnail} = $c->req->upload('front_thumbnail');
}
$form->process(
posted => $posted,
@ -226,7 +230,7 @@ sub devmod_create :Chained('base') :PathPart('model/create') :Args(0) :Does(ACL)
delete $form->values->{reseller};
my $ft = File::Type->new();
foreach(qw/front_image mac_image/){
foreach(qw/front_image mac_image front_thumbnail/){
if($form->values->{$_}) {
my $image = delete $form->values->{$_};
$form->values->{$_} = $image->slurp;
@ -287,7 +291,7 @@ sub devmod_base :Chained('base') :PathPart('model') :CaptureArgs(1) {
);
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/device'));
}
my $devmod = $c->stash->{devmod_rs}->find($devmod_id,{'+columns' => [qw/mac_image front_image/]});
my $devmod = $c->stash->{devmod_rs}->find($devmod_id,{'+columns' => [qw/mac_image front_image front_thumbnail/]});
unless($devmod) {
NGCP::Panel::Utils::Message::error(
c => $c,
@ -368,6 +372,7 @@ sub devmod_edit :Chained('devmod_base') :PathPart('edit') :Args(0) :Does(ACL) :A
if($posted) {
$c->req->params->{front_image} = $c->req->upload('front_image');
$c->req->params->{mac_image} = $c->req->upload('mac_image');
$c->req->params->{front_thumbnail} = $c->req->upload('front_thumbnail');
}
$form->process(
@ -395,7 +400,7 @@ sub devmod_edit :Chained('devmod_base') :PathPart('edit') :Args(0) :Does(ACL) :A
}
delete $form->values->{reseller};
foreach (qw/front_image mac_image/){
foreach (qw/front_image mac_image front_thumbnail/){
if($form->values->{$_}) {
my $image = delete $form->values->{$_};
$form->values->{$_} = $image->slurp;
@ -476,6 +481,33 @@ sub devmod_download_macimage :Chained('devmod_base') :PathPart('macimage') :Args
$c->response->body($devmod->mac_image);
}
sub devmod_download_frontthumbnail_by_profile :Chained('devprof_base') :PathPart('frontthumbnail') :Args(0) {
my ($self, $c) = @_;
my $devprof = $c->stash->{devprof};
my $devmod = $devprof->config->device;
unless($devmod->front_thumbnail) {
$c->log->info("No device thumbnail for profile id " . $c->stash->{devprof}->id . ", redirecting to front image");
$c->res->redirect($c->uri_for_action("/device/devmod_download_frontimage_by_profile", [$c->stash->{devprof}->id]));
return;
}
$c->response->content_type($devmod->front_thumbnail_type);
$c->response->body($devmod->front_thumbnail);
}
sub devmod_download_frontthumbnail :Chained('devmod_base') :PathPart('frontthumbnail') :Args(0) {
my ($self, $c) = @_;
my $devmod = $c->stash->{devmod};
unless($devmod->front_thumbnail) {
$c->log->info("No device thumbnail for model id " . $c->stash->{devmod}->id . ", redirecting to front image");
$c->res->redirect($c->uri_for_action("/device/devmod_download_frontimage", [$c->stash->{devmod}->id]));
return;
}
$c->response->content_type($devmod->front_thumbnail_type);
$c->response->body($devmod->front_thumbnail);
}
sub devfw_ajax :Chained('base') :PathPart('firmware/ajax') :Args(0) :Does(ACL) :ACLDetachTo('/denied_page') :AllowedRole(admin) :AllowedRole(reseller) {
my ($self, $c) = @_;
@ -515,7 +547,7 @@ sub devfw_create :Chained('base') :PathPart('firmware/create') :Args(0) :Does(AC
$schema->txn_do(sub {
my $file = delete $form->values->{data};
$form->values->{filename} = $file->filename;
my $devmod = $c->stash->{devmod_rs}->find($form->values->{device}{id},{'+columns' => [qw/mac_image front_image/]});
my $devmod = $c->stash->{devmod_rs}->find($form->values->{device}{id},{'+columns' => [qw/mac_image front_image front_thumbnail/]});
my $devfw = $devmod->create_related('autoprov_firmwares', $form->values);
if ($file->size) {
NGCP::Panel::Utils::DeviceFirmware::insert_firmware_data(
@ -702,7 +734,7 @@ sub devconf_create :Chained('base') :PathPart('config/create') :Args(0) :Does(AC
try {
my $schema = $c->model('DB');
$schema->txn_do(sub {
my $devmod = $c->stash->{devmod_rs}->find($form->values->{device}{id},{'+columns' => [qw/mac_image front_image/]});
my $devmod = $c->stash->{devmod_rs}->find($form->values->{device}{id},{'+columns' => [qw/mac_image front_image front_thumbnail/]});
my $devconf = $devmod->create_related('autoprov_configs', $form->values);
delete $c->session->{created_objects}->{device};
$c->session->{created_objects}->{config} = { id => $devconf->id };
@ -925,7 +957,7 @@ sub devprof_extensions :Chained('devprof_base') :PathPart('extensions') :Args(0)
my $rs = $c->stash->{devprof}->config->device->autoprov_extensions_link;
my $device_info = { $c->stash->{devprof}->config->device->get_inflated_columns };
foreach(qw/front_image mac_image/){
foreach(qw/front_image mac_image front_thumbnail/){
delete $device_info->{$_};
}

@ -66,6 +66,13 @@ has_field 'front_image' => (
max_size => '67108864', # 64MB
);
has_field 'front_thumbnail' => (
type => 'Upload',
required => 0,
label => 'Front Image Thumbnail',
max_size => '67108864', # 64MB
);
has_field 'mac_image' => (
type => 'Upload',
required => 0,
@ -501,7 +508,7 @@ has_field 'save' => (
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/vendor model type extensions_num connectable_models linerange linerange_add bootstrap_method bootstrap_uri bootstrap_config_http_sync_method bootstrap_config_http_sync_uri bootstrap_config_http_sync_params bootstrap_config_redirect_panasonic_user bootstrap_config_redirect_panasonic_password bootstrap_config_redirect_yealink_user bootstrap_config_redirect_yealink_password bootstrap_config_redirect_polycom_user bootstrap_config_redirect_polycom_password bootstrap_config_redirect_polycom_profile bootstrap_config_redirect_grandstream_cid bootstrap_config_redirect_grandstream_key bootstrap_config_redirect_sipwise_user bootstrap_config_redirect_sipwise_password bootstrap_config_profile_sipwise_user bootstrap_config_profile_sipwise_password front_image mac_image/],
render_list => [qw/vendor model type extensions_num connectable_models linerange linerange_add bootstrap_method bootstrap_uri bootstrap_config_http_sync_method bootstrap_config_http_sync_uri bootstrap_config_http_sync_params bootstrap_config_redirect_panasonic_user bootstrap_config_redirect_panasonic_password bootstrap_config_redirect_yealink_user bootstrap_config_redirect_yealink_password bootstrap_config_redirect_polycom_user bootstrap_config_redirect_polycom_password bootstrap_config_redirect_polycom_profile bootstrap_config_redirect_grandstream_cid bootstrap_config_redirect_grandstream_key bootstrap_config_redirect_sipwise_user bootstrap_config_redirect_sipwise_password bootstrap_config_profile_sipwise_user bootstrap_config_profile_sipwise_password front_image front_thumbnail mac_image/],
);
has_block 'actions' => (

@ -15,7 +15,7 @@ override 'field_list' => sub {
return unless $c;
super();
foreach my $f(qw/front_image mac_image linerange_add/) {
foreach my $f(qw/front_image mac_image front_thumbnail linerange_add/) {
$self->field($f)->inactive(1);
}
};

@ -29,7 +29,7 @@ has_field 'save' => (
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/reseller vendor model type extensions_num connectable_models linerange linerange_add bootstrap_method bootstrap_uri bootstrap_config_http_sync_method bootstrap_config_http_sync_uri bootstrap_config_http_sync_params bootstrap_config_redirect_panasonic_user bootstrap_config_redirect_panasonic_password bootstrap_config_redirect_yealink_user bootstrap_config_redirect_yealink_password bootstrap_config_redirect_polycom_user bootstrap_config_redirect_polycom_password bootstrap_config_redirect_polycom_profile bootstrap_config_redirect_snom_user bootstrap_config_redirect_snom_password bootstrap_config_redirect_grandstream_cid bootstrap_config_redirect_grandstream_key front_image mac_image/],
render_list => [qw/reseller vendor model type extensions_num connectable_models linerange linerange_add bootstrap_method bootstrap_uri bootstrap_config_http_sync_method bootstrap_config_http_sync_uri bootstrap_config_http_sync_params bootstrap_config_redirect_panasonic_user bootstrap_config_redirect_panasonic_password bootstrap_config_redirect_yealink_user bootstrap_config_redirect_yealink_password bootstrap_config_redirect_polycom_user bootstrap_config_redirect_polycom_password bootstrap_config_redirect_polycom_profile bootstrap_config_redirect_snom_user bootstrap_config_redirect_snom_password bootstrap_config_redirect_grandstream_cid bootstrap_config_redirect_grandstream_key front_image front_thumbnail mac_image/],
);
has_block 'actions' => (

@ -77,6 +77,7 @@ sub resource_from_item {
my %resource = $item->get_inflated_columns;
delete $resource{front_image};
delete $resource{mac_image};
delete $resource{front_thumbnail};
my ($form) = $self->get_form($c);
return unless $self->validate_form(
@ -138,13 +139,18 @@ sub process_form_resource{
my $ft = File::Type->new();
if($resource->{front_image}) {
my $front_image = delete $resource->{front_image};
$resource->{front_image} = $front_image->slurp;
my $image = delete $resource->{front_image};
$resource->{front_image} = $image->slurp;
$resource->{front_image_type} = $ft->mime_type($resource->{front_image});
}
if($resource->{front_thumbnail}) {
my $image = delete $resource->{front_thumbnail};
$resource->{front_thumbnail} = $image->slurp;
$resource->{front_thumbnail_type} = $ft->mime_type($resource->{front_thumbnail});
}
if($resource->{mac_image}) {
my $front_image = delete $resource->{mac_image};
$resource->{mac_image} = $front_image->slurp;
my $image = delete $resource->{mac_image};
$resource->{mac_image} = $image->slurp;
$resource->{mac_image_type} = $ft->mime_type($resource->{mac_image});
}

@ -343,7 +343,7 @@ $(function() {
<tbody>
[% FOR dev IN pbx_devices -%]
<tr class="sw_action_row">
<td><img src="[% c.uri_for_action('/device/devmod_download_frontimage', [ dev.profile.config.device.id]) %]" style="height:40px"/></td>
<td><img src="[% c.uri_for_action('/device/devmod_download_frontthumbnail', [ dev.profile.config.device.id]) %]" style="height:40px"/></td>
<td>[% dev.station_name %]</td>
<td>
<ul style="list-style-type:none; margin-left:0">

@ -68,6 +68,7 @@ $fake_data->set_data_from_script({
#TODO: can check big files
#front_image => [ dirname($0).'/resources/api_devicemodels_front_image.jpg' ],
front_image => [ dirname($0).'/resources/empty.txt' ],
front_thumbnail => [ dirname($0).'/resources/empty.txt' ],
},
'query' => [ ['model','json','model'] ],
'no_delete_available' => 1,

Loading…
Cancel
Save