%PDF- %PDF-
Direktori : /backups/router/usr/local/opnsense/mvc/app/views/OPNsense/CaptivePortal/ |
Current File : //backups/router/usr/local/opnsense/mvc/app/views/OPNsense/CaptivePortal/vouchers.volt |
{# # Copyright (c) 2014-2015 Deciso B.V. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. #} <script src="{{ cache_safe('/ui/js/moment-with-locales.min.js') }}"></script> <script> $( document ).ready(function() { /** * update zone list */ function updateVoucherProviders() { ajaxGet("/api/captiveportal/voucher/listProviders/", {}, function(data, status) { if (status == "success") { $('#voucher-providers').html(""); $.each(data, function(key, value) { $('#voucher-providers').append($("<option></option>").attr("value", value).text(value)); }); if ($('#voucher-providers option').length > 0) { // link on change event $('#voucher-providers').on('change', function(){ updateVoucherGroupList(); }); // initial load voucher list updateVoucherGroupList(); } else { // A voucher server is needed before we can add vouchers, alert user BootstrapDialog.alert('{{ lang._('Please setup a voucher server first (%sgoto auth servers%s)') | format('<a href="/system_authservers.php">','</a>') }}'); } } }); } /** * update voucher group list */ function updateVoucherGroupList() { var voucher_provider = $('#voucher-providers').find("option:selected").val(); ajaxGet("/api/captiveportal/voucher/listVoucherGroups/" + voucher_provider + "/", {}, function(data, status) { if (status == "success") { $('#voucher-groups').html(""); $.each(data, function(key, value) { $('#voucher-groups').append($("<option></option>").attr("value", value).text(value)); }); $('.selectpicker').selectpicker('refresh'); // link on change event $('#voucher-groups').on('change', function(){ updateVoucherList(); }); // initial load voucher list updateVoucherList(); } }); } /** * list vouchers in grid */ function updateVoucherList() { var voucher_provider = $('#voucher-providers').find("option:selected").val(); var voucher_group = $('#voucher-groups').find("option:selected").val(); var gridopt = { ajax: false, selection: true, multiSelect: true, converters: { // convert datetime type fields from unix timestamp to readable format datetime: { from: function (value) { return moment(parseInt(value) * 1000); }, to: function (value) { return value == 0 ? "" : value.format("lll"); } } } }; $("#grid-vouchers").bootgrid('destroy'); ajaxGet("/api/captiveportal/voucher/listVouchers/" + voucher_provider + "/" + voucher_group + "/", {}, function (data, status) { if (status == "success") { $("#grid-vouchers > tbody > tr").remove(); $.each(data, function (key, value) { var fields = ["username", "starttime", "endtime", "expirytime", "state"]; let tr_str = '<tr>'; for (var i = 0; i < fields.length; i++) { if (value[fields[i]] != null) { tr_str += '<td>' + value[fields[i]] + '</td>'; } else { tr_str += '<td></td>'; } } tr_str += '</tr>'; $("#grid-vouchers > tbody").append(tr_str); }); } $("#grid-vouchers").bootgrid(gridopt); } ); } /** * link voucher delete button */ $("#deleteVoucherGroup").click(function(){ var voucher_group = $('#voucher-groups').find("option:selected").val(); var voucher_provider = $('#voucher-providers').find("option:selected").val(); if (voucher_group != undefined) { BootstrapDialog.show({ type:BootstrapDialog.TYPE_DANGER, title: '{{ lang._('Remove voucher group') }} "' + voucher_group + '" @ ' + voucher_provider, message: '{{ lang._('All vouchers within this group will be deleted') }}', buttons: [{ icon: 'fa fa-trash-o', label: '{{ lang._('Yes') }}', cssClass: 'btn-primary', action: function(dlg){ ajaxCall( "/api/captiveportal/voucher/dropVoucherGroup/" + voucher_provider + "/" + voucher_group + '/', {}, function(data,status){ // reload grid after delete updateVoucherGroupList(); }); dlg.close(); } }, { label: '{{ lang._('Close') }}', action: function(dlg){ dlg.close(); } }] }); } }); /** * link create vouchers button */ $("#showVoucherModal").click(function(){ $("#voucher-groupname").val(moment().format('YYYYMMDDHHmmss')); $("#generateVouchers").modal(); }); /** * link actual voucher generation in dialog */ $("#generateVoucherBtn").click(function(){ $('#generatevouchererror').html(''); $('#generatevouchererror').hide(); var voucher_provider = $('#voucher-providers').find("option:selected").val(); var voucher_validity = $("#voucher-validity").val(); var voucher_expirytime = $("#voucher-expiry").val(); var voucher_quantity = $("#voucher-quantity").val(); var voucher_groupname = $("#voucher-groupname").val(); if (!$.isNumeric(voucher_validity) || !$.isNumeric(voucher_quantity) || !$.isNumeric(voucher_expirytime)) { // don't try to generate vouchers when validity, expirytime or quantity are invalid var error = $('<p />'); error.text("{{ lang._('The validity, expiry time and the quantity of vouchers must be integers.') }}"); $('#generatevouchererror').append(error); $('#generatevouchererror').show(); return; } ajaxCall("/api/captiveportal/voucher/generateVouchers/" + voucher_provider + "/", { 'count':voucher_quantity, 'validity':voucher_validity, 'expirytime':voucher_expirytime, 'vouchergroup':voucher_groupname }, function(data, status){ // convert json to csv data var output_data = 'username,password,vouchergroup,expirytime,validity\n'; $.each(data, function( key, value ) { output_data = output_data.concat('"', value['username'], '",'); output_data = output_data.concat('"', value['password'], '",'); output_data = output_data.concat('"', value['vouchergroup'], '",'); output_data = output_data.concat('"', value['expirytime'], '",'); output_data = output_data.concat('"', value['validity'], '"\n'); }); // generate download link and send data to the client if ($('#downloadFile').length) { // remove previous link $('#downloadFile').remove(); } $('<a></a>') .attr('id','downloadFile') .attr('href','data:text/csv;charset=utf8,' + encodeURIComponent(output_data)) .attr('download',voucher_groupname.toLowerCase() + '.csv') .appendTo('body'); $('#downloadFile').ready(function() { if ( window.navigator.msSaveOrOpenBlob && window.Blob ) { var blob = new Blob( [ output_data ], { type: "text/csv" } ); navigator.msSaveOrOpenBlob( blob, voucher_groupname.toLowerCase() + '.csv' ); } else { $('#downloadFile').get(0).click(); } }); $("#generateVouchers").modal('hide'); // reload grid after creating new vouchers updateVoucherGroupList(); }); }); $("#dropExpired").click(function(){ var voucher_group = $('#voucher-groups').find("option:selected").val(); var voucher_provider = $('#voucher-providers').find("option:selected").val(); if (voucher_group != undefined) { BootstrapDialog.show({ type:BootstrapDialog.TYPE_DANGER, title: '{{ lang._('Remove expired vouchers') }} "' + voucher_group + '" @ ' + voucher_provider, message: '{{ lang._('All expired vouchers within this group will be deleted') }}', buttons: [{ icon: 'fa fa-trash-o', label: '{{ lang._('Yes') }}', cssClass: 'btn-primary', action: function(dlg){ ajaxCall("/api/captiveportal/voucher/dropExpiredVouchers/" + voucher_provider + "/" + voucher_group + '/', {}, function(data,status){ // reload grid after delete updateVoucherGroupList(); }); dlg.close(); } }, { label: '{{ lang._('Close') }}', action: function(dlg){ dlg.close(); } }] }); } }); /** * Expire selected vouchers */ $("#expireVouchers").click(function(){ var voucher_provider = $('#voucher-providers').find("option:selected").val(); BootstrapDialog.show({ type:BootstrapDialog.TYPE_DANGER, title: voucher_provider, message: '{{ lang._('Expire all selected vouchers?') }}', buttons: [{ icon: 'fa fa-trash-o', label: '{{ lang._('Yes') }}', cssClass: 'btn-primary', action: function(dlg){ var rows =$("#grid-vouchers").bootgrid('getSelectedRows'); if (rows != undefined) { var deferreds = []; $.each(rows, function (key, username) { deferreds.push( ajaxCall("/api/captiveportal/voucher/expireVoucher/" + voucher_provider + "/", {username:username}, null )); }); $.when.apply(null, deferreds).done(function(){ updateVoucherGroupList(); }); } dlg.close(); } }, { label: '{{ lang._('Close') }}', action: function(dlg){ dlg.close(); } }] }); }); $("#voucher-validity").change(function(){ if ($(this).children(":selected").attr("id") == 'voucher-validity-custom') { $("#voucher-validity-custom-data").show(); } else { $("#voucher-validity-custom-data").hide(); } }); $("#voucher-validity-custom-data").keyup(function(){ $("#voucher-validity-custom").val($(this).val()*60); }); $("#voucher-expiry").change(function(){ if ($(this).children(":selected").attr("id") == 'voucher-expiry-custom') { $("#voucher-expiry-custom-data").show(); } else { $("#voucher-expiry-custom-data").hide(); } }); $("#voucher-expiry-custom-data").keyup(function(){ $("#voucher-expiry-custom").val($(this).val()*3600); }); $("#voucher-quantity").change(function(){ if ($(this).children(":selected").attr("id") == 'voucher-quantity-custom') { $("#voucher-quantity-custom-data").show(); } else { $("#voucher-quantity-custom-data").hide(); } }); $("#voucher-quantity-custom-data").keyup(function(){ $("#voucher-quantity-custom").val($(this).val()); }); updateVoucherProviders(); $('.selectpicker').selectpicker('refresh'); }); </script> <div class="content-box"> <div class="content-box-main"> <div class="table-responsive"> <div class="col-sm-12"> <div class="pull-right"> <select id="voucher-providers" class="selectpicker" data-width="200px"></select> <select id="voucher-groups" class="selectpicker" data-width="200px"></select> <button id="deleteVoucherGroup" type="button" class="btn btn-xs btn-default"> <span class="fa fa-trash-o fa-2x"></span> </button> <hr/> </div> </div> <div class="col-sm-12"> <table id="grid-vouchers" class="table table-condensed table-hover table-striped table-responsive"> <thead> <tr> <th data-column-id="username" data-type="string" data-identifier="true">{{ lang._('Voucher') }}</th> <th data-column-id="starttime" data-type="datetime">{{ lang._('Valid from') }}</th> <th data-column-id="endtime" data-type="datetime">{{ lang._('Valid to') }}</th> <th data-column-id="expirytime" data-type="datetime">{{ lang._('Expires at') }}</th> <th data-column-id="state" data-type="string">{{ lang._('State') }}</th> </tr> </thead> <tbody> </tbody> <tfoot> </tfoot> </table> </div> <div class="col-sm-12"> <div class="row"> <div class="col-sm-12"> <div class="pull-right"> <button id="expireVouchers" type="button" class="btn btn-default"> <span>{{ lang._('Expire selected vouchers') }}</span> <span class="fa fa-trash"></span> </button> <button id="dropExpired" type="button" class="btn btn-default"> <span>{{ lang._('Drop expired vouchers') }}</span> <span class="fa fa-trash"></span> </button> <button id="showVoucherModal" type="button" class="btn btn-default"> <span>{{ lang._('Create vouchers') }}</span> <span class="fa fa-ticket"></span> </button> </div> </div> </div> <hr/> </div> </div> </div> </div> <!-- Dialog to render new vouchers --> <div id="generateVouchers" class="modal fade" role="dialog"> <div class="modal-dialog"> <!-- Modal content--> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title">{{ lang._('Generate vouchers') }}</h4> </div> <div class="modal-body"> <div id="generatevouchererror" class="alert alert-danger" role="alert" style="display: none"></div> <table class="table table-striped table-condensed table-responsive"> <thead> <tr> <th>{{ lang._('Setting') }}</th> <th>{{ lang._('Value') }}</th> </tr> </thead> <tbody> <tr> <td>{{ lang._('Validity') }}</td> <td> <select id="voucher-validity" class="selectpicker" data-width="200px"> <option value="14400">{{ lang._('4 hours') }}</option> <option value="28800">{{ lang._('8 hours') }}</option> <option value="86400">{{ lang._('1 day') }}</option> <option value="172800">{{ lang._('2 days') }}</option> <option value="259200">{{ lang._('3 days') }}</option> <option value="345600">{{ lang._('4 days') }}</option> <option value="432000">{{ lang._('5 days') }}</option> <option value="518400">{{ lang._('6 days') }}</option> <option value="604800">{{ lang._('1 week') }}</option> <option value="1209600">{{ lang._('2 weeks') }}</option> <option id="voucher-validity-custom" value="">{{ lang._('Custom (minutes)') }}</option> </select> <input type="text" id="voucher-validity-custom-data" style="display:none;"> </td> </tr> <tr> <td>{{ lang._('Expires in') }}</td> <td> <select id="voucher-expiry" class="selectpicker" data-width="200px"> <option value="0">{{ lang._('never') }}</option> <option value="21600">{{ lang._('6 hours') }}</option> <option value="43200">{{ lang._('12 hours') }}</option> <option value="86400">{{ lang._('1 day') }}</option> <option value="172800">{{ lang._('2 days') }}</option> <option value="259200">{{ lang._('3 days') }}</option> <option value="345600">{{ lang._('4 days') }}</option> <option value="432000">{{ lang._('5 days') }}</option> <option value="518400">{{ lang._('6 days') }}</option> <option value="604800">{{ lang._('1 week') }}</option> <option value="1209600">{{ lang._('2 weeks') }}</option> <option value="1814400">{{ lang._('3 weeks') }}</option> <option value="2419200">{{ lang._('1 month') }}</option> <option value="4838400">{{ lang._('2 months') }}</option> <option value="7257600">{{ lang._('3 months') }}</option> <option id="voucher-expiry-custom" value="">{{ lang._('Custom (hours)') }}</option> </select> <input type="text" id="voucher-expiry-custom-data" style="display:none;"> </td> </tr> <tr> <td>{{ lang._('Number of vouchers') }}</td> <td> <select id="voucher-quantity" class="selectpicker" data-width="200px"> <option value="1">1</option> <option value="5">5</option> <option value="10">10</option> <option value="25">25</option> <option value="50">50</option> <option value="100">100</option> <option value="250">250</option> <option id="voucher-quantity-custom" value="">{{ lang._('Custom') }}</option> </select> <input type="text" id="voucher-quantity-custom-data" style="display:none;"> </td> </tr> <tr> <td>{{ lang._('Groupname') }}</td> <td> <input id="voucher-groupname" type="text"> </td> </tr> </tbody> </table> </div> <div class="modal-footer"> <button id="generateVoucherBtn" type="button" class="btn btn-primary">{{ lang._('Generate') }}</button> <button type="button" class="btn btn-default" data-dismiss="modal">{{ lang._('Close') }}</button> </div> </div> </div> </div>