PHP Classes

File: templates/admin/mrc_settings.twig

Recommend this page to a friend!
  Packages of Matthew Asham   Binkterm PHP   templates/admin/mrc_settings.twig   Download  
File: templates/admin/mrc_settings.twig
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Binkterm PHP
Bulletin board system based on the Web
Author: By
Last change:
Date: 5 days ago
Size: 19,454 bytes
 

Contents

Class file image Download
{% extends "base.twig" %} {% block title %}{{ t('ui.admin.mrc_settings.page_title') }}{% endblock %} {% block content %} <div class="container-fluid"> <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom"> <h1 class="h2">{{ t('ui.admin.mrc_settings.heading') }}</h1> <div></div> </div> <div class="alert alert-info"> <i class="bi bi-info-circle"></i> <strong>{{ t('ui.admin.mrc_settings.note_label') }}:</strong> {{ t('ui.admin.mrc_settings.note_text') }} {{ t('ui.admin.mrc_settings.note_enable_text') }} <a href="/admin/webdoors" class="alert-link">{{ t('ui.admin.mrc_settings.webdoors_admin') }}</a>. </div> <div class="row g-4" id="mrcSettingsCards"> <!-- General Settings --> <div class="col-lg-6"> <div class="card shadow h-100"> <div class="card-header"> <h6 class="mb-0">{{ t('ui.admin.mrc_settings.general_settings') }}</h6> </div> <div class="card-body"> <div id="mrcGeneralAlert"></div> <form id="mrcGeneralForm"> <div class="form-check form-switch mb-3"> <input class="form-check-input" type="checkbox" id="mrcEnabled"> <label class="form-check-label" for="mrcEnabled">{{ t('ui.admin.mrc_settings.enable_daemon') }}</label> <small class="form-text d-block text-muted"> </small> </div> <hr> <h6 class="mb-3">{{ t('ui.admin.mrc_settings.server_connection') }}</h6> <div class="mb-3"> <label class="form-label" for="mrcServerHost">{{ t('ui.admin.mrc_settings.server_host') }}</label> <input type="text" class="form-control" id="mrcServerHost" placeholder="{{ t('ui.admin.mrc_settings.placeholder.server_host', {}, locale, ['common']) }}"> </div> <div class="mb-3"> <label class="form-label" for="mrcServerPort">{{ t('ui.admin.mrc_settings.server_port_non_ssl') }}</label> <input type="number" class="form-control" id="mrcServerPort" min="1" max="65535" value="50000"> </div> <div class="mb-3"> <label class="form-label" for="mrcServerSslPort">{{ t('ui.admin.mrc_settings.server_port_ssl') }}</label> <input type="number" class="form-control" id="mrcServerSslPort" min="1" max="65535" value="50001"> </div> <div class="form-check form-switch mb-3"> <input class="form-check-input" type="checkbox" id="mrcUseSsl" checked> <label class="form-check-label" for="mrcUseSsl">{{ t('ui.admin.mrc_settings.use_ssl_connection') }}</label> <small class="form-text d-block text-muted"> {{ t('ui.admin.mrc_settings.use_ssl_help') }} </small> </div> <button type="button" class="btn btn-primary" onclick="saveMrcSettings()"> {{ t('ui.admin.mrc_settings.save_general_settings') }} </button> </form> </div> </div> </div> <!-- BBS Identity --> <div class="col-lg-6"> <div class="card shadow h-100"> <div class="card-header"> <h6 class="mb-0">{{ t('ui.admin.mrc_settings.bbs_identity') }}</h6> </div> <div class="card-body"> <div id="mrcIdentityAlert"></div> <form id="mrcIdentityForm"> <div class="mb-3"> <label class="form-label" for="mrcBbsName">{{ t('ui.admin.mrc_settings.bbs_name') }}</label> <input type="text" class="form-control" id="mrcBbsName" maxlength="64" placeholder="{{ t('ui.admin.mrc_settings.placeholder.bbs_name', {}, locale, ['common']) }}"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.bbs_name_help') }}</small> </div> <div class="mb-3"> <label class="form-label" for="mrcPlatform">{{ t('ui.admin.mrc_settings.platform_info') }}</label> <input type="text" class="form-control" id="mrcPlatform" placeholder="{{ t('ui.admin.mrc_settings.placeholder.platform', {}, locale, ['common']) }}"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.platform_info_help') }}</small> </div> <div class="mb-3"> <label class="form-label" for="mrcSysop">{{ t('ui.admin.mrc_settings.sysop_name') }}</label> <input type="text" class="form-control" id="mrcSysop" placeholder="{{ t('ui.admin.mrc_settings.placeholder.sysop', {}, locale, ['common']) }}"> </div> <hr> <h6 class="mb-3">{{ t('ui.admin.mrc_settings.bbs_information') }}</h6> <div class="mb-3"> <label class="form-label" for="mrcWebsite">{{ t('ui.admin.mrc_settings.website_url') }}</label> <input type="url" class="form-control" id="mrcWebsite" placeholder="{{ t('ui.admin.mrc_settings.placeholder.website', {}, locale, ['common']) }}"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.info_optional_help') }}</small> </div> <div class="mb-3"> <label class="form-label" for="mrcTelnet">{{ t('ui.admin.mrc_settings.telnet_address') }}</label> <input type="text" class="form-control" id="mrcTelnet" placeholder="{{ t('ui.admin.mrc_settings.placeholder.telnet', {}, locale, ['common']) }}"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.info_optional_help') }}</small> </div> <div class="mb-3"> <label class="form-label" for="mrcDescription">{{ t('ui.admin.mrc_settings.bbs_description') }}</label> <textarea class="form-control" id="mrcDescription" rows="3" placeholder="{{ t('ui.admin.mrc_settings.placeholder.description', {}, locale, ['common']) }}"></textarea> </div> <button type="button" class="btn btn-primary" onclick="saveMrcSettings()"> {{ t('ui.admin.mrc_settings.save_identity_settings') }} </button> </form> </div> </div> </div> <!-- Connection Settings --> <div class="col-lg-6"> <div class="card shadow h-100"> <div class="card-header"> <h6 class="mb-0">{{ t('ui.admin.mrc_settings.connection_settings') }}</h6> </div> <div class="card-body"> <div id="mrcConnectionAlert"></div> <form id="mrcConnectionForm"> <div class="form-check form-switch mb-3"> <input class="form-check-input" type="checkbox" id="mrcAutoReconnect" checked> <label class="form-check-label" for="mrcAutoReconnect">{{ t('ui.admin.mrc_settings.auto_reconnect') }}</label> <small class="form-text d-block text-muted"> {{ t('ui.admin.mrc_settings.auto_reconnect_help') }} </small> </div> <div class="mb-3"> <label class="form-label" for="mrcReconnectDelay">{{ t('ui.admin.mrc_settings.reconnect_delay') }}</label> <input type="number" class="form-control" id="mrcReconnectDelay" min="5" max="300" value="30"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.reconnect_delay_help') }}</small> </div> <div class="mb-3"> <label class="form-label" for="mrcPingInterval">{{ t('ui.admin.mrc_settings.ping_interval') }}</label> <input type="number" class="form-control" id="mrcPingInterval" min="30" max="300" value="60"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.ping_interval_help') }}</small> </div> <div class="mb-3"> <label class="form-label" for="mrcKeepaliveTimeout">{{ t('ui.admin.mrc_settings.keepalive_timeout') }}</label> <input type="number" class="form-control" id="mrcKeepaliveTimeout" min="60" max="600" value="125"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.keepalive_timeout_help') }}</small> </div> <button type="button" class="btn btn-primary" onclick="saveMrcSettings()"> {{ t('ui.admin.mrc_settings.save_connection_settings') }} </button> </form> </div> </div> </div> <!-- Room Settings --> <div class="col-lg-6"> <div class="card shadow h-100"> <div class="card-header"> <h6 class="mb-0">{{ t('ui.admin.mrc_settings.room_settings') }}</h6> </div> <div class="card-body"> <div id="mrcRoomAlert"></div> <form id="mrcRoomForm"> <div class="mb-3"> <label class="form-label" for="mrcDefaultRoom">{{ t('ui.admin.mrc_settings.default_room') }}</label> <input type="text" class="form-control" id="mrcDefaultRoom" value="lobby"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.default_room_help') }}</small> </div> <div class="mb-3"> <label class="form-label" for="mrcAutoJoinRooms">{{ t('ui.admin.mrc_settings.auto_join_rooms') }}</label> <input type="text" class="form-control" id="mrcAutoJoinRooms" value="lobby"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.auto_join_rooms_help') }}</small> </div> <hr> <h6 class="mb-3">{{ t('ui.admin.mrc_settings.message_settings') }}</h6> <div class="mb-3"> <label class="form-label" for="mrcMaxMessageLength">{{ t('ui.admin.mrc_settings.max_message_length') }}</label> <input type="number" class="form-control" id="mrcMaxMessageLength" min="80" max="255" value="140"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.max_message_length_help') }}</small> </div> <div class="mb-3"> <label class="form-label" for="mrcHistoryLimit">{{ t('ui.admin.mrc_settings.history_limit') }}</label> <input type="number" class="form-control" id="mrcHistoryLimit" min="100" max="10000" value="1000"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.history_limit_help') }}</small> </div> <div class="mb-3"> <label class="form-label" for="mrcPruneAfterDays">{{ t('ui.admin.mrc_settings.prune_after_days') }}</label> <input type="number" class="form-control" id="mrcPruneAfterDays" min="1" max="365" value="30"> <small class="form-text text-muted">{{ t('ui.admin.mrc_settings.prune_after_days_help') }}</small> </div> <button type="button" class="btn btn-primary" onclick="saveMrcSettings()"> {{ t('ui.admin.mrc_settings.save_room_settings') }} </button> </form> </div> </div> </div> </div> </div> <script> // Global config variable let mrcConfig = {}; function uiT(key, fallback, params = {}) { if (window.t) { return window.t(key, params, fallback); } return fallback; } // Load MRC configuration on page load $(document).ready(function() { loadMrcSettings(); }); /** * Load MRC settings from admin daemon */ async function loadMrcSettings() { setSettingsLoading('#mrcSettingsCards', true); try { const response = await $.ajax({ url: '/admin/api/mrc-settings', method: 'GET', dataType: 'json' }); if (response.success) { mrcConfig = response.config; populateMrcForm(); setSettingsLoading('#mrcSettingsCards', false); } else { showAlert('mrcGeneralAlert', 'danger', uiT('ui.admin.mrc_settings.load_failed', 'Failed to load MRC settings')); } } catch (error) { console.error('Failed to load MRC settings:', error); showAlert('mrcGeneralAlert', 'danger', uiT('ui.admin.mrc_settings.load_error', 'Error loading MRC settings')); } } /** * Populate form fields with loaded config */ function populateMrcForm() { // General settings $('#mrcEnabled').prop('checked', mrcConfig.enabled || false); $('#mrcServerHost').val(mrcConfig.server?.host || 'mrc.bottomlessabyss.net'); $('#mrcServerPort').val(mrcConfig.server?.port || 50000); $('#mrcServerSslPort').val(mrcConfig.server?.ssl_port || 50001); $('#mrcUseSsl').prop('checked', mrcConfig.server?.use_ssl !== false); // BBS identity $('#mrcBbsName').val(mrcConfig.bbs?.name || 'BinktermPHP BBS'); $('#mrcPlatform').val(mrcConfig.bbs?.platform || 'BINKTERMPHP/Linux64/1.3.0'); $('#mrcSysop').val(mrcConfig.bbs?.sysop || 'Sysop'); // BBS info $('#mrcWebsite').val(mrcConfig.info?.website || ''); $('#mrcTelnet').val(mrcConfig.info?.telnet || ''); $('#mrcDescription').val(mrcConfig.info?.description || ''); // Connection settings $('#mrcAutoReconnect').prop('checked', mrcConfig.connection?.auto_reconnect !== false); $('#mrcReconnectDelay').val(mrcConfig.connection?.reconnect_delay || 30); $('#mrcPingInterval').val(mrcConfig.connection?.ping_interval || 60); $('#mrcKeepaliveTimeout').val(mrcConfig.connection?.keepalive_timeout || 125); // Room settings $('#mrcDefaultRoom').val(mrcConfig.rooms?.default || 'lobby'); $('#mrcAutoJoinRooms').val((mrcConfig.rooms?.auto_join || ['lobby']).join(', ')); // Message settings $('#mrcMaxMessageLength').val(mrcConfig.messages?.max_length || 140); $('#mrcHistoryLimit').val(mrcConfig.messages?.history_limit || 1000); $('#mrcPruneAfterDays').val(mrcConfig.messages?.prune_after_days || 30); } /** * Save MRC settings to admin daemon */ async function saveMrcSettings() { // Collect all form values const config = { enabled: $('#mrcEnabled').is(':checked'), server: { host: $('#mrcServerHost').val(), port: parseInt($('#mrcServerPort').val()), use_ssl: $('#mrcUseSsl').is(':checked'), ssl_port: parseInt($('#mrcServerSslPort').val()) }, bbs: { name: $('#mrcBbsName').val(), platform: $('#mrcPlatform').val(), sysop: $('#mrcSysop').val() }, connection: { auto_reconnect: $('#mrcAutoReconnect').is(':checked'), reconnect_delay: parseInt($('#mrcReconnectDelay').val()), ping_interval: parseInt($('#mrcPingInterval').val()), handshake_timeout: mrcConfig.connection?.handshake_timeout || 1, keepalive_timeout: parseInt($('#mrcKeepaliveTimeout').val()) }, rooms: { default: $('#mrcDefaultRoom').val(), auto_join: $('#mrcAutoJoinRooms').val().split(',').map(r => r.trim()).filter(r => r) }, messages: { max_length: parseInt($('#mrcMaxMessageLength').val()), history_limit: parseInt($('#mrcHistoryLimit').val()), prune_after_days: parseInt($('#mrcPruneAfterDays').val()) }, info: { website: $('#mrcWebsite').val(), telnet: $('#mrcTelnet').val(), ssh: mrcConfig.info?.ssh || '', description: $('#mrcDescription').val() } }; try { const response = await $.ajax({ url: '/admin/api/mrc-settings', method: 'POST', contentType: 'application/json', data: JSON.stringify({ config }), dataType: 'json' }); if (response.success) { const successMessage = window.getApiMessage ? window.getApiMessage(response, uiT('ui.admin.mrc_settings.saved_success', 'MRC settings saved successfully')) : uiT('ui.admin.mrc_settings.saved_success', 'MRC settings saved successfully'); showAlert('mrcGeneralAlert', 'success', successMessage); mrcConfig = response.config; // If enabled status changed, suggest daemon restart if (config.enabled !== mrcConfig.enabled) { showAlert('mrcGeneralAlert', 'warning', uiT('ui.admin.mrc_settings.restart_required', 'Settings saved. Restart the daemon to apply changes.')); } } else { showAlert('mrcGeneralAlert', 'danger', uiT('ui.admin.mrc_settings.save_failed', 'Failed to save MRC settings')); } } catch (error) { console.error('Failed to save MRC settings:', error); showAlert('mrcGeneralAlert', 'danger', uiT('ui.admin.mrc_settings.save_error', 'Error saving MRC settings')); } } /** * Show alert message */ function showAlert(containerId, type, message) { const alertHtml = ` <div class="alert alert-${type} alert-dismissible fade show" role="alert"> ${message} <button type="button" class="btn-close" data-bs-dismiss="alert"></button> </div> `; $(`#${containerId}`).html(alertHtml); // Auto-dismiss after 5 seconds setTimeout(() => { const alertEl = document.querySelector(`#${containerId} .alert`); if (!alertEl) { return; } if (window.bootstrap && window.bootstrap.Alert) { window.bootstrap.Alert.getOrCreateInstance(alertEl).close(); return; } alertEl.remove(); }, 5000); } </script> {% endblock %}