task_config_templ.templ 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package app
  2. import (
  3. "github.com/seaweedfs/seaweedfs/weed/admin/maintenance"
  4. "github.com/seaweedfs/seaweedfs/weed/admin/view/components"
  5. )
  6. // TaskConfigTemplData represents data for templ-based task configuration
  7. type TaskConfigTemplData struct {
  8. TaskType maintenance.MaintenanceTaskType
  9. TaskName string
  10. TaskIcon string
  11. Description string
  12. ConfigSections []components.ConfigSectionData
  13. }
  14. templ TaskConfigTempl(data *TaskConfigTemplData) {
  15. <div class="container-fluid">
  16. <div class="row mb-4">
  17. <div class="col-12">
  18. <div class="d-flex justify-content-between align-items-center">
  19. <h2 class="mb-0">
  20. <i class={data.TaskIcon + " me-2"}></i>
  21. {data.TaskName} Configuration
  22. </h2>
  23. <div class="btn-group">
  24. <a href="/maintenance/config" class="btn btn-outline-secondary">
  25. <i class="fas fa-arrow-left me-1"></i>
  26. Back to Configuration
  27. </a>
  28. <a href="/maintenance/queue" class="btn btn-outline-info">
  29. <i class="fas fa-list me-1"></i>
  30. View Queue
  31. </a>
  32. </div>
  33. </div>
  34. </div>
  35. </div>
  36. <div class="row mb-4">
  37. <div class="col-12">
  38. <div class="alert alert-info" role="alert">
  39. <i class="fas fa-info-circle me-2"></i>
  40. {data.Description}
  41. </div>
  42. </div>
  43. </div>
  44. <form method="POST" class="needs-validation" novalidate>
  45. <!-- Render all configuration sections -->
  46. for _, section := range data.ConfigSections {
  47. @components.ConfigSection(section)
  48. }
  49. <!-- Form actions -->
  50. <div class="row">
  51. <div class="col-12">
  52. <div class="card">
  53. <div class="card-body">
  54. <div class="d-flex justify-content-between">
  55. <div>
  56. <button type="submit" class="btn btn-primary">
  57. <i class="fas fa-save me-1"></i>
  58. Save Configuration
  59. </button>
  60. <button type="button" class="btn btn-outline-secondary ms-2" onclick="resetForm()">
  61. <i class="fas fa-undo me-1"></i>
  62. Reset
  63. </button>
  64. </div>
  65. <div>
  66. <button type="button" class="btn btn-outline-info" onclick="testConfiguration()">
  67. <i class="fas fa-play me-1"></i>
  68. Test Configuration
  69. </button>
  70. </div>
  71. </div>
  72. </div>
  73. </div>
  74. </div>
  75. </div>
  76. </form>
  77. </div>
  78. <script>
  79. // Form validation
  80. (function() {
  81. 'use strict';
  82. window.addEventListener('load', function() {
  83. var forms = document.getElementsByClassName('needs-validation');
  84. var validation = Array.prototype.filter.call(forms, function(form) {
  85. form.addEventListener('submit', function(event) {
  86. if (form.checkValidity() === false) {
  87. event.preventDefault();
  88. event.stopPropagation();
  89. }
  90. form.classList.add('was-validated');
  91. }, false);
  92. });
  93. }, false);
  94. })();
  95. // Auto-save functionality
  96. let autoSaveTimeout;
  97. function autoSave() {
  98. clearTimeout(autoSaveTimeout);
  99. autoSaveTimeout = setTimeout(function() {
  100. const formData = new FormData(document.querySelector('form'));
  101. localStorage.setItem('task_config_' + '{data.TaskType}', JSON.stringify(Object.fromEntries(formData)));
  102. }, 1000);
  103. }
  104. // Add auto-save listeners to all form inputs
  105. document.addEventListener('DOMContentLoaded', function() {
  106. const form = document.querySelector('form');
  107. if (form) {
  108. form.addEventListener('input', autoSave);
  109. form.addEventListener('change', autoSave);
  110. }
  111. });
  112. // Reset form function
  113. function resetForm() {
  114. if (confirm('Are you sure you want to reset all changes?')) {
  115. location.reload();
  116. }
  117. }
  118. // Test configuration function
  119. function testConfiguration() {
  120. const formData = new FormData(document.querySelector('form'));
  121. // Show loading state
  122. const testBtn = document.querySelector('button[onclick="testConfiguration()"]');
  123. const originalContent = testBtn.innerHTML;
  124. testBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Testing...';
  125. testBtn.disabled = true;
  126. fetch('/maintenance/config/{data.TaskType}/test', {
  127. method: 'POST',
  128. body: formData
  129. })
  130. .then(response => response.json())
  131. .then(data => {
  132. if (data.success) {
  133. alert('Configuration test successful!');
  134. } else {
  135. alert('Configuration test failed: ' + data.error);
  136. }
  137. })
  138. .catch(error => {
  139. alert('Test failed: ' + error);
  140. })
  141. .finally(() => {
  142. testBtn.innerHTML = originalContent;
  143. testBtn.disabled = false;
  144. });
  145. }
  146. </script>
  147. }