diff --git a/lib/NGCP/Panel/Controller/API/PbxDeviceModelImages.pm b/lib/NGCP/Panel/Controller/API/PbxDeviceModelImages.pm index 231a501ddd..9ae359a042 100644 --- a/lib/NGCP/Panel/Controller/API/PbxDeviceModelImages.pm +++ b/lib/NGCP/Panel/Controller/API/PbxDeviceModelImages.pm @@ -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 {}, diff --git a/lib/NGCP/Panel/Controller/API/PbxDeviceModelImagesItem.pm b/lib/NGCP/Panel/Controller/API/PbxDeviceModelImagesItem.pm index 69d93230ab..22a6671de1 100644 --- a/lib/NGCP/Panel/Controller/API/PbxDeviceModelImagesItem.pm +++ b/lib/NGCP/Panel/Controller/API/PbxDeviceModelImagesItem.pm @@ -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; diff --git a/lib/NGCP/Panel/Controller/API/PbxDeviceModels.pm b/lib/NGCP/Panel/Controller/API/PbxDeviceModels.pm index 0910e6275b..b2bdad8ab5 100644 --- a/lib/NGCP/Panel/Controller/API/PbxDeviceModels.pm +++ b/lib/NGCP/Panel/Controller/API/PbxDeviceModels.pm @@ -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 PbxDeviceConfigs. 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.: 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/ This resource is read-only to subscriberadmins.'; + return 'Specifies a model to be set in PbxDeviceConfigs. 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.: 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/ This resource is read-only to subscriberadmins.'; }; sub query_params { diff --git a/lib/NGCP/Panel/Controller/API/PbxDeviceModelsItem.pm b/lib/NGCP/Panel/Controller/API/PbxDeviceModelsItem.pm index c2d57fb6cd..5bfd773929 100644 --- a/lib/NGCP/Panel/Controller/API/PbxDeviceModelsItem.pm +++ b/lib/NGCP/Panel/Controller/API/PbxDeviceModelsItem.pm @@ -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/], diff --git a/lib/NGCP/Panel/Controller/Device.pm b/lib/NGCP/Panel/Controller/Device.pm index 9f32c2756e..797a3e1d70 100644 --- a/lib/NGCP/Panel/Controller/Device.pm +++ b/lib/NGCP/Panel/Controller/Device.pm @@ -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->{$_}; } diff --git a/lib/NGCP/Panel/Form/Device/Model.pm b/lib/NGCP/Panel/Form/Device/Model.pm index c29edcbf86..487953cca4 100644 --- a/lib/NGCP/Panel/Form/Device/Model.pm +++ b/lib/NGCP/Panel/Form/Device/Model.pm @@ -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' => ( diff --git a/lib/NGCP/Panel/Form/Device/ModelAPI.pm b/lib/NGCP/Panel/Form/Device/ModelAPI.pm index 93ca67e178..e882dea4cf 100644 --- a/lib/NGCP/Panel/Form/Device/ModelAPI.pm +++ b/lib/NGCP/Panel/Form/Device/ModelAPI.pm @@ -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); } }; diff --git a/lib/NGCP/Panel/Form/Device/ModelAdmin.pm b/lib/NGCP/Panel/Form/Device/ModelAdmin.pm index 64dec77e02..a31bedead2 100644 --- a/lib/NGCP/Panel/Form/Device/ModelAdmin.pm +++ b/lib/NGCP/Panel/Form/Device/ModelAdmin.pm @@ -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' => ( diff --git a/lib/NGCP/Panel/Role/API/PbxDeviceModels.pm b/lib/NGCP/Panel/Role/API/PbxDeviceModels.pm index 7a55d03989..767865afaa 100644 --- a/lib/NGCP/Panel/Role/API/PbxDeviceModels.pm +++ b/lib/NGCP/Panel/Role/API/PbxDeviceModels.pm @@ -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}); } diff --git a/share/templates/customer/details.tt b/share/templates/customer/details.tt index dca2658962..e5132aad42 100644 --- a/share/templates/customer/details.tt +++ b/share/templates/customer/details.tt @@ -343,7 +343,7 @@ $(function() { [% FOR dev IN pbx_devices -%] - + [% dev.station_name %]