From f680f334ce2e00076d003d4290c72fd672e1f08e Mon Sep 17 00:00:00 2001
From: Ruel Tmeizeh - RuhNet
Date: Sat, 22 Nov 2025 02:20:28 -0500
Subject: [PATCH] outbound faxing via API
---
app.js | 85 +++++++++++++++++-
i18n/de-DE.json | 10 +++
i18n/en-US.json | 10 +++
style/app.css | 183 ++++++++++++++++++++++++++++++++++++++
views/outbound-faxes.html | 16 ++++
5 files changed, 301 insertions(+), 3 deletions(-)
create mode 100644 style/app.css
diff --git a/app.js b/app.js
index eb19d2a..9b29d3c 100644
--- a/app.js
+++ b/app.js
@@ -29,7 +29,8 @@ define(function(require) {
default: 7,
max: 31
},
- faxboxes: {}
+ faxboxes: {},
+ faxnumbers: []
},
initApp: function(callback) {
@@ -46,7 +47,8 @@ define(function(require) {
self.getFaxData(function(results) {
self.appFlags.faxboxes = _.keyBy(results.faxboxes, 'id');
-console.log(_.size(self.appFlags.faxboxes));
+ //console.log(_.size(self.appFlags.faxboxes));
+ self.appFlags.faxnumbers = results.faxnumbers;
var menus = [
{
tabs: [
@@ -90,6 +92,11 @@ console.log(_.size(self.appFlags.faxboxes));
callback(null, faxboxes);
});
},
+ faxnumbers: function(callback) {
+ self.getFaxNumbers(function(faxnumbers) {
+ callback(null, faxnumbers);
+ });
+ },
storage: function(callback) {
self.getStorage(function(storage) {
callback(null, storage);
@@ -119,6 +126,7 @@ console.log(_.size(self.appFlags.faxboxes));
parent = args.container || $('#fax_app_container .app-content-wrapper'),
dataTemplate = {
faxboxes: self.appFlags.faxboxes,
+ faxnumbers: self.appFlags.faxnumbers,
count: _.size(self.appFlags.faxboxes)
},
template = $(self.getTemplate({
@@ -315,6 +323,20 @@ console.log(_.size(self.appFlags.faxboxes));
cb.prop('checked', !cb.prop('checked'));
afterSelect();
});
+
+ template.on('change', '#sendfax_uploaded_file', function() {
+ if ($(this).val()) { // Check if a file is selected
+ $('.send-fax-button').prop('disabled', false);
+ } else {
+ $('.send-fax-button').prop('disabled', true);
+ }
+ });
+
+ template.on('click', '.send-fax-button', function(e) {
+ e.preventDefault();
+ self.sendFaxUpload(template);
+ });
+
},
displayListFaxes: function(type, container, faxboxId) {
@@ -734,8 +756,65 @@ console.log(_.size(self.appFlags.faxboxes));
callback && callback(data.data);
}
});
+ },
+
+ sendFaxUpload: function(template) {
+ var self = this;
+ var toNumber = template.find('#sendfax_to_number').val();
+ var fromNumber = template.find('#sendfax_from_number').val();
+ var file = template.find('#sendfax_uploaded_file')[0].files[0];
+ if (!file) return monster.ui.alert(self.i18n.active().fax.outbound.missingFile);
+ if (!toNumber) return monster.ui.alert(self.i18n.active().fax.outbound.missingTo);
+ if (!fromNumber || fromNumber == 'none') return monster.ui.alert(self.i18n.active().fax.outbound.missingFrom);
+
+ var selected_faxbox = template.find('.select-faxbox').val();
+
+ //create json blob to use in form data
+ var jsonData = JSON.stringify({data: {from_number: fromNumber, to_number: toNumber, faxbox_id: selected_faxbox}});
+ var jsonBlob = new Blob([jsonData], { type: 'application/json' });
+
+ var form = new FormData();
+ form.set("json", jsonBlob);
+ form.set('file', file, file.name);
+
+ $.ajax({
+ url: monster.config.api.default + 'accounts/' + self.accountId + '/faxes',
+ method: 'put',
+ processData: false,
+ contentType: false,
+ headers: { 'X-Auth-Token': monster.util.getAuthToken() },
+ data: form,
+ success: function(res) {
+ monster.ui.toast({ type: "success", message: self.i18n.active().fax.outbound.success });
+ console.log(res.data);
+ template.find('#sendfax_uploaded_file').val(null);
+ },
+ error: function(err) {
+ console.log(err);
+ monster.ui.alert('Error
err.responseText
');
+ }
+ });
+ },
+
+ getFaxNumbers: function(callback) {
+ var self = this;
+
+ self.callApi({
+ resource: 'numbers.listAll',
+ data: {
+ accountId: self.accountId,
+ filters: { paginate: false }
+ },
+ success: function(res, status) {
+ var numbers = _.map(res.data.numbers, function(n, number) {
+ return {number: number};
+ });
+ callback && callback(numbers);
+ }
+ });
}
- };
+
+ }; //app
return app;
});
diff --git a/i18n/de-DE.json b/i18n/de-DE.json
index d478acb..da6fb73 100644
--- a/i18n/de-DE.json
+++ b/i18n/de-DE.json
@@ -77,6 +77,16 @@
"outbound": "Ausgehende Faxe",
"storage": "Speicher"
},
+ "outbound": {
+ "enterToNumber": "Enter Fax To Number",
+ "missingFile": "You must choose a PDF or TIFF file to send",
+ "missingFrom": "You must select the source number.",
+ "missingTo": "You must enter the destination fax number.",
+ "selectFile": "Upload your file (PDF or TIFF format)",
+ "selectNumber": "Select From Number",
+ "sendFax": "Send Fax",
+ "success": "fax has been queued for sending"
+ },
"title": "Faxportal",
"CDRPopup": {
"title": "Faxdetails"
diff --git a/i18n/en-US.json b/i18n/en-US.json
index 5d6f0ab..af1a409 100644
--- a/i18n/en-US.json
+++ b/i18n/en-US.json
@@ -7,6 +7,16 @@
"logs": "Email-to-Fax Logs",
"storage": "Storage"
},
+ "outbound": {
+ "enterToNumber": "Enter Fax To Number",
+ "missingFile": "You must choose a PDF or TIFF file to send",
+ "missingFrom": "You must select the source number.",
+ "missingTo": "You must enter the destination fax number.",
+ "selectFile": "Upload your file (PDF or TIFF format)",
+ "selectNumber": "Select From Number",
+ "sendFax": "Send Fax",
+ "success": "fax has been queued for sending"
+ },
"table": {
"columns": {
"status": "Status",
diff --git a/style/app.css b/style/app.css
new file mode 100644
index 0000000..ef60a98
--- /dev/null
+++ b/style/app.css
@@ -0,0 +1,183 @@
+/* _colors.scss */
+/* unique color names */
+/* semantic color names */
+/* Default empty state */
+.faxes-container.empty .empty-state {
+ display: block; }
+
+.faxes-container .empty-state {
+ display: none;
+ text-align: center; }
+
+.faxes-container .empty-state .headline {
+ font-size: 22px;
+ margin-top: 35px; }
+
+.faxes-container .empty-state .sub-headline {
+ color: #606069;
+ font-size: 16px;
+ margin-top: 13px; }
+
+.faxes-container .empty-state .count {
+ font-weight: bold;
+ margin-left: 5px;
+ margin-right: 5px; }
+
+.faxes-container .empty-state .faxboxes-list {
+ margin-top: 30px;
+ width: 450px;
+ text-align: left; }
+
+.faxes-container .empty-state .chosen-drop {
+ width: 450px; }
+
+.faxes-container .empty-state .chosen-container > a,
+.faxes-container .main-header .chosen-container > a {
+ height: 40px;
+ line-height: 40px;
+ width: 450px; }
+
+.faxes-container .main-header {
+ margin-bottom: 25px; }
+
+.faxes-container .main-header .select-header {
+ color: #606069;
+ margin-bottom: 5px; }
+
+.faxes-container .main-header .chosen-drop,
+.faxes-container .main-header .chosen-container > a,
+.faxes-container .main-header .faxboxes-list,
+.faxes-container .main-header .faxbox-selector {
+ width: 300px; }
+
+.faxes-container .main-header > * {
+ display: inline-block;
+ margin-right: 25px; }
+
+.faxes-container .main-header #refresh_faxbox {
+ margin-top: 35px; }
+
+.faxes-container .main-header .faxbox-selector .chosen-container .chosen-single span {
+ font-size: 18px; }
+
+.faxes-container .data-state {
+ display: none; }
+
+.faxes-container .loading-state {
+ display: none;
+ background: #fff none repeat scroll 0 0;
+ border: 1px dashed #aaa;
+ font-size: 60px;
+ padding: 50px;
+ text-align: center;
+ position: relative;
+ top: 50px; }
+
+.faxes-container .faxboxes-list {
+ display: block;
+ margin: auto;
+ width: 400px; }
+
+/* Action Bar */
+.faxes-container.empty .filters.search,
+.faxes-container.empty .filters.basic-actions > *,
+.faxes-container.empty .main-header {
+ display: none; }
+
+.faxes-container .filters.basic-actions {
+ display: inline-block; }
+
+.faxes-container:not(.empty) .action-bar {
+ display: block; }
+
+.faxes-container .action-bar {
+ display: none; }
+
+.faxes-container .action-bar .filters > :first-child {
+ margin-left: 0; }
+
+.faxes-container .action-bar .margin-left {
+ margin-left: 10px; }
+
+.faxes-container .action-bar .hidable {
+ display: inline-block; }
+
+.faxes-container .action-bar .hidable.hidden {
+ display: none; }
+
+/* Table */
+.faxes-container .faxbox-table table {
+ margin-top: 0; }
+
+.faxes-container .faxbox-table tbody tr > td:first-child .monster-checkbox {
+ margin-right: 10px;
+ margin-top: 8px; }
+
+.faxes-container .faxbox-table .select-cell {
+ min-width: 20px !important;
+ width: 20px; }
+
+.faxes-container .faxbox-table .select-line {
+ cursor: pointer; }
+
+.faxes-container .faxbox-table tr .bottom-line {
+ color: #707079;
+ font-size: 12px; }
+
+.faxes-container .faxbox-table td.no-padding {
+ padding: 0; }
+
+.faxes-container .faxbox-table .status {
+ text-transform: uppercase; }
+
+.faxes-container .filter-by-date .date-ranges > * {
+ margin: 0 10px 0 0;
+ vertical-align: middle; }
+
+.faxes-container .filter-by-date .date-ranges > span {
+ margin-right: 5px; }
+
+.faxes-container .filter-by-date .date-ranges input.date-filter {
+ height: 24px;
+ width: 90px; }
+
+.faxes-container .filter-by-date .date-ranges i.fa-calendar {
+ margin-left: -30px;
+ margin-right: 20px; }
+
+.faxes-container .filter-by-date {
+ float: right;
+ line-height: 30px;
+ margin-left: 30px; }
+
+.faxes-container .filter-by-date.active .expand-dates {
+ float: right; }
+
+.faxes-container .filter-by-date .date-ranges,
+.faxes-container .filter-by-date.active .expand-dates {
+ display: none; }
+
+.faxes-container .filter-by-date.active .date-ranges {
+ display: block; }
+
+/* CDR Popup */
+#faxbox_cdr_details_dialog {
+ width: 750px;
+ margin: 15px; }
+
+/* Faxes log */
+#smtp_logs_container .table .detail-link {
+ margin: 0px; }
+
+#smtp_logs_grid {
+ clear: right; }
+
+#smtp_logs_detail_dialog {
+ width: 700px;
+ padding: 15px; }
+
+#smtp_logs_detail_dialog tr,
+#smtp_logs_detail_dialog td {
+ line-height: 15px;
+ padding: 2px;
+ white-space: normal; }
diff --git a/views/outbound-faxes.html b/views/outbound-faxes.html
index 9644734..e089e37 100644
--- a/views/outbound-faxes.html
+++ b/views/outbound-faxes.html
@@ -15,6 +15,22 @@
+
+
+
+
+
+
+