- Added GitHub spec-kit for development workflow - Standardized file signatures to Descomplicar® format - Updated development configuration 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
424 lines
21 KiB
PHP
424 lines
21 KiB
PHP
/**
|
|
* Descomplicar® Crescimento Digital
|
|
* https://descomplicar.pt
|
|
*/
|
|
|
|
<?php defined('BASEPATH') or exit('No direct script access allowed'); ?>
|
|
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="panel_s">
|
|
<div class="panel-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h4 class="no-margin">
|
|
<i class="fa fa-cog" aria-hidden="true"></i>
|
|
<?php echo _l('desk_moloni_configuration'); ?>
|
|
</h4>
|
|
</div>
|
|
<div class="col-md-6 text-right">
|
|
<?php if (has_permission('desk_moloni', '', 'edit')) { ?>
|
|
<button type="button" class="btn btn-info" id="test-connection">
|
|
<i class="fa fa-plug"></i> <?php echo _l('desk_moloni_test_connection'); ?>
|
|
</button>
|
|
<?php } ?>
|
|
<a href="<?php echo admin_url('modules/desk_moloni'); ?>" class="btn btn-default">
|
|
<i class="fa fa-arrow-left"></i> <?php echo _l('back_to_dashboard'); ?>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<hr class="hr-panel-separator" />
|
|
|
|
<!-- OAuth Configuration Section -->
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="panel_s">
|
|
<div class="panel-body">
|
|
<h4><i class="fa fa-key"></i> <?php echo _l('desk_moloni_oauth_configuration'); ?></h4>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div id="oauth-status-card" class="alert <?php echo $oauth_status['configured'] ? 'alert-success' : 'alert-warning'; ?>">
|
|
<div class="row">
|
|
<div class="col-md-2">
|
|
<i class="fa <?php echo $oauth_status['configured'] ? 'fa-check-circle' : 'fa-exclamation-triangle'; ?> fa-3x"></i>
|
|
</div>
|
|
<div class="col-md-10">
|
|
<h5><?php echo $oauth_status['configured'] ? _l('desk_moloni_oauth_configured') : _l('desk_moloni_oauth_not_configured'); ?></h5>
|
|
<p><?php echo $oauth_status['message']; ?></p>
|
|
<?php if ($oauth_status['configured'] && !empty($oauth_status['expires_at'])) { ?>
|
|
<small><?php echo _l('desk_moloni_token_expires'); ?>: <?php echo date('Y-m-d H:i:s', strtotime($oauth_status['expires_at'])); ?></small>
|
|
<?php } ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<?php if (!$oauth_status['configured']) { ?>
|
|
<a href="<?php echo admin_url('modules/desk_moloni/oauth_setup'); ?>" class="btn btn-primary btn-lg btn-block">
|
|
<i class="fa fa-magic"></i> <?php echo _l('desk_moloni_setup_oauth'); ?>
|
|
</a>
|
|
<?php } else { ?>
|
|
<div class="btn-group-vertical btn-block">
|
|
<a href="<?php echo admin_url('modules/desk_moloni/oauth_setup'); ?>" class="btn btn-default">
|
|
<i class="fa fa-edit"></i> <?php echo _l('desk_moloni_update_oauth'); ?>
|
|
</a>
|
|
<button type="button" class="btn btn-warning" id="refresh-token">
|
|
<i class="fa fa-refresh"></i> <?php echo _l('desk_moloni_refresh_token'); ?>
|
|
</button>
|
|
</div>
|
|
<?php } ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Main Configuration Form -->
|
|
<?php echo form_open(admin_url('modules/desk_moloni/config'), array('id' => 'desk-moloni-config-form')); ?>
|
|
|
|
<!-- General Settings -->
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="panel_s">
|
|
<div class="panel-body">
|
|
<h4><i class="fa fa-sliders"></i> <?php echo _l('desk_moloni_general_settings'); ?></h4>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<?php
|
|
$selected = isset($config['moloni_company_id']) ? $config['moloni_company_id'] : '';
|
|
echo render_select('moloni_company_id', $companies, array('id', 'name'), 'desk_moloni_company', $selected, array('data-none-selected-text' => _l('desk_moloni_select_company')));
|
|
?>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<div class="checkbox checkbox-primary">
|
|
<input type="checkbox" name="sync_enabled" id="sync_enabled" value="1" <?php echo (isset($config['sync_enabled']) && $config['sync_enabled'] === '1') ? 'checked' : ''; ?>>
|
|
<label for="sync_enabled"><?php echo _l('desk_moloni_enable_sync'); ?></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Auto-Sync Settings -->
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="panel_s">
|
|
<div class="panel-body">
|
|
<h4><i class="fa fa-refresh"></i> <?php echo _l('desk_moloni_auto_sync_settings'); ?></h4>
|
|
|
|
<div class="row">
|
|
<div class="col-md-3">
|
|
<div class="form-group">
|
|
<div class="checkbox checkbox-primary">
|
|
<input type="checkbox" name="auto_sync_clients" id="auto_sync_clients" value="1" <?php echo (isset($config['auto_sync_clients']) && $config['auto_sync_clients'] === '1') ? 'checked' : ''; ?>>
|
|
<label for="auto_sync_clients">
|
|
<i class="fa fa-users"></i> <?php echo _l('desk_moloni_auto_sync_clients'); ?>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-group">
|
|
<div class="checkbox checkbox-primary">
|
|
<input type="checkbox" name="auto_sync_products" id="auto_sync_products" value="1" <?php echo (isset($config['auto_sync_products']) && $config['auto_sync_products'] === '1') ? 'checked' : ''; ?>>
|
|
<label for="auto_sync_products">
|
|
<i class="fa fa-cube"></i> <?php echo _l('desk_moloni_auto_sync_products'); ?>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-group">
|
|
<div class="checkbox checkbox-primary">
|
|
<input type="checkbox" name="auto_sync_invoices" id="auto_sync_invoices" value="1" <?php echo (isset($config['auto_sync_invoices']) && $config['auto_sync_invoices'] === '1') ? 'checked' : ''; ?>>
|
|
<label for="auto_sync_invoices">
|
|
<i class="fa fa-file-text"></i> <?php echo _l('desk_moloni_auto_sync_invoices'); ?>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-group">
|
|
<div class="checkbox checkbox-primary">
|
|
<input type="checkbox" name="auto_sync_estimates" id="auto_sync_estimates" value="1" <?php echo (isset($config['auto_sync_estimates']) && $config['auto_sync_estimates'] === '1') ? 'checked' : ''; ?>>
|
|
<label for="auto_sync_estimates">
|
|
<i class="fa fa-file-o"></i> <?php echo _l('desk_moloni_auto_sync_estimates'); ?>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="form-group">
|
|
<div class="checkbox checkbox-primary">
|
|
<input type="checkbox" name="queue_processing_enabled" id="queue_processing_enabled" value="1" <?php echo (isset($config['queue_processing_enabled']) && $config['queue_processing_enabled'] === '1') ? 'checked' : ''; ?>>
|
|
<label for="queue_processing_enabled">
|
|
<i class="fa fa-cogs"></i> <?php echo _l('desk_moloni_enable_queue_processing'); ?>
|
|
</label>
|
|
</div>
|
|
<small class="help-block"><?php echo _l('desk_moloni_queue_processing_help'); ?></small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Advanced Settings -->
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="panel_s">
|
|
<div class="panel-body">
|
|
<h4><i class="fa fa-cogs"></i> <?php echo _l('desk_moloni_advanced_settings'); ?></h4>
|
|
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<?php
|
|
$retry_attempts = isset($config['max_retry_attempts']) ? $config['max_retry_attempts'] : '3';
|
|
echo render_input('max_retry_attempts', 'desk_moloni_max_retry_attempts', $retry_attempts, 'number', array('min' => '1', 'max' => '10'));
|
|
?>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<?php
|
|
$sync_interval = isset($config['sync_interval']) ? $config['sync_interval'] : '300';
|
|
echo render_input('sync_interval', 'desk_moloni_sync_interval_seconds', $sync_interval, 'number', array('min' => '60', 'max' => '3600'));
|
|
?>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<?php
|
|
$batch_size = isset($config['batch_size']) ? $config['batch_size'] : '50';
|
|
echo render_input('batch_size', 'desk_moloni_batch_size', $batch_size, 'number', array('min' => '1', 'max' => '200'));
|
|
?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="form-group">
|
|
<div class="checkbox checkbox-primary">
|
|
<input type="checkbox" name="debug_mode" id="debug_mode" value="1" <?php echo (isset($config['debug_mode']) && $config['debug_mode'] === '1') ? 'checked' : ''; ?>>
|
|
<label for="debug_mode">
|
|
<i class="fa fa-bug"></i> <?php echo _l('desk_moloni_enable_debug_mode'); ?>
|
|
</label>
|
|
</div>
|
|
<small class="help-block"><?php echo _l('desk_moloni_debug_mode_help'); ?></small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Save Button -->
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<?php if (has_permission('desk_moloni', '', 'edit')) { ?>
|
|
<button type="submit" class="btn btn-primary pull-right">
|
|
<i class="fa fa-save"></i> <?php echo _l('save_settings'); ?>
|
|
</button>
|
|
<?php } ?>
|
|
<div class="clearfix"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php echo form_close(); ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
$(document).ready(function() {
|
|
// Test connection functionality
|
|
$('#test-connection').on('click', function() {
|
|
var btn = $(this);
|
|
var originalText = btn.html();
|
|
|
|
btn.prop('disabled', true)
|
|
.html('<i class="fa fa-spinner fa-spin"></i> <?php echo _l("desk_moloni_testing_connection"); ?>');
|
|
|
|
$.ajax({
|
|
url: admin_url + 'modules/desk_moloni/test_connection',
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
if (response.success) {
|
|
alert_float('success', response.message);
|
|
} else {
|
|
alert_float('danger', response.message);
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
alert_float('danger', '<?php echo _l("desk_moloni_connection_test_failed"); ?>');
|
|
},
|
|
complete: function() {
|
|
btn.prop('disabled', false).html(originalText);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Refresh token functionality
|
|
$('#refresh-token').on('click', function() {
|
|
var btn = $(this);
|
|
var originalText = btn.html();
|
|
|
|
if (!confirm('<?php echo _l("desk_moloni_refresh_token_confirm"); ?>')) {
|
|
return;
|
|
}
|
|
|
|
btn.prop('disabled', true)
|
|
.html('<i class="fa fa-spinner fa-spin"></i> <?php echo _l("desk_moloni_refreshing_token"); ?>');
|
|
|
|
$.ajax({
|
|
url: admin_url + 'modules/desk_moloni/refresh_oauth_token',
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
if (response.success) {
|
|
alert_float('success', response.message);
|
|
setTimeout(function() {
|
|
window.location.reload();
|
|
}, 1500);
|
|
} else {
|
|
alert_float('danger', response.message);
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
alert_float('danger', '<?php echo _l("desk_moloni_token_refresh_failed"); ?>');
|
|
},
|
|
complete: function() {
|
|
btn.prop('disabled', false).html(originalText);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Form validation
|
|
$('#desk-moloni-config-form').on('submit', function(e) {
|
|
var syncEnabled = $('#sync_enabled').is(':checked');
|
|
var oauthConfigured = <?php echo $oauth_status['configured'] ? 'true' : 'false'; ?>;
|
|
|
|
if (syncEnabled && !oauthConfigured) {
|
|
e.preventDefault();
|
|
alert_float('warning', '<?php echo _l("desk_moloni_oauth_required_for_sync"); ?>');
|
|
return false;
|
|
}
|
|
|
|
// Show loading state
|
|
var submitBtn = $(this).find('button[type="submit"]');
|
|
var originalText = submitBtn.html();
|
|
|
|
submitBtn.prop('disabled', true)
|
|
.html('<i class="fa fa-spinner fa-spin"></i> <?php echo _l("saving"); ?>');
|
|
|
|
// Re-enable button after form submission
|
|
setTimeout(function() {
|
|
submitBtn.prop('disabled', false).html(originalText);
|
|
}, 3000);
|
|
});
|
|
|
|
// Enable/disable auto-sync options based on main sync toggle
|
|
$('#sync_enabled').on('change', function() {
|
|
var autoSyncCheckboxes = $('input[name^="auto_sync_"]');
|
|
|
|
if ($(this).is(':checked')) {
|
|
autoSyncCheckboxes.prop('disabled', false);
|
|
} else {
|
|
autoSyncCheckboxes.prop('checked', false).prop('disabled', true);
|
|
}
|
|
}).trigger('change');
|
|
|
|
// Show/hide advanced settings
|
|
var advancedVisible = false;
|
|
$('#show-advanced-settings').on('click', function(e) {
|
|
e.preventDefault();
|
|
var advancedPanel = $('#advanced-settings-panel');
|
|
|
|
if (advancedVisible) {
|
|
advancedPanel.slideUp();
|
|
$(this).html('<i class="fa fa-plus"></i> <?php echo _l("desk_moloni_show_advanced_settings"); ?>');
|
|
advancedVisible = false;
|
|
} else {
|
|
advancedPanel.slideDown();
|
|
$(this).html('<i class="fa fa-minus"></i> <?php echo _l("desk_moloni_hide_advanced_settings"); ?>');
|
|
advancedVisible = true;
|
|
}
|
|
});
|
|
|
|
// Input validation
|
|
$('input[type="number"]').on('input', function() {
|
|
var value = parseInt($(this).val());
|
|
var min = parseInt($(this).attr('min'));
|
|
var max = parseInt($(this).attr('max'));
|
|
|
|
if (value < min) {
|
|
$(this).val(min);
|
|
} else if (value > max) {
|
|
$(this).val(max);
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
.alert {
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.alert .fa {
|
|
margin-right: 0;
|
|
}
|
|
|
|
.checkbox label {
|
|
padding-left: 0;
|
|
}
|
|
|
|
.checkbox input[type="checkbox"] {
|
|
margin-right: 8px;
|
|
position: relative;
|
|
top: 1px;
|
|
}
|
|
|
|
.panel_s {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.form-group .help-block {
|
|
margin-top: 5px;
|
|
font-size: 11px;
|
|
color: #737373;
|
|
}
|
|
|
|
#oauth-status-card {
|
|
border: none;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
#oauth-status-card h5 {
|
|
margin-top: 0;
|
|
font-weight: bold;
|
|
}
|
|
|
|
#oauth-status-card .fa {
|
|
margin-right: 0;
|
|
}
|
|
|
|
.btn-group-vertical .btn {
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.btn-group-vertical .btn:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
</style>
|