main.html 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta name="viewport" content="width=device-width, initial-scale=1">
  5. <meta charset="UTF-8">
  6. <title>tcgui</title>
  7. <link rel="stylesheet" href="{{ url_for('static', filename='gui_styles.css') }}">
  8. <style>
  9. body {
  10. font-family: Arial, sans-serif;
  11. background-color: #e3f2fd;
  12. color: #333;
  13. padding: 20px;
  14. }
  15. .container {
  16. max-width: 1200px;
  17. margin: auto;
  18. background: white;
  19. padding: 20px;
  20. border-radius: 10px;
  21. box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  22. }
  23. h1, h2 {
  24. text-align: center;
  25. color: #1e88e5;
  26. }
  27. ul {
  28. list-style-type: none;
  29. padding: 0;
  30. margin: 0 auto;
  31. width: fit-content; /* Adjust to fit the content */
  32. }
  33. ul li {
  34. text-align: left;
  35. margin-right: 10px;
  36. }
  37. ul li a {
  38. text-decoration: none;
  39. color: #1e88e5;
  40. }
  41. table {
  42. width: 100%;
  43. border-collapse: collapse;
  44. margin: 20px 0;
  45. }
  46. th, td {
  47. padding: 12px;
  48. border: 1px solid #ddd;
  49. text-align: center;
  50. }
  51. th {
  52. background-color: #1e88e5;
  53. color: white;
  54. }
  55. tr:nth-child(even) {
  56. background-color: #f1f8e9;
  57. }
  58. .btn-container {
  59. text-align: center;
  60. margin-top: 20px;
  61. }
  62. .pure-button {
  63. padding: 10px 20px;
  64. font-size: 16px;
  65. margin: 5px;
  66. color: white;
  67. border: none;
  68. border-radius: 5px;
  69. cursor: pointer;
  70. }
  71. .pure-button-primary {
  72. background-color: #1e88e5;
  73. }
  74. .button-remove {
  75. background-color: #d32f2f;
  76. }
  77. .input-group {
  78. display: flex;
  79. align-items: center;
  80. }
  81. .input-group input, .input-group select {
  82. margin-right: 10px;
  83. }
  84. .tcgui-value-cell.modified {
  85. background: rgb(121, 168, 255);
  86. }
  87. .tcgui-input-cell {
  88. text-align: left;
  89. }
  90. </style>
  91. </head>
  92. <body>
  93. <div class="container">
  94. <h1>TCGUI - {{ rules|length }} Available Interfaces</h1>
  95. <ul>
  96. {% for rule in rules %}
  97. <li><a href="#{{ rule['name'] }}">{{ rule['name'] }} ({{ rule['ip'] }})</a></li>
  98. {% endfor %}
  99. </ul>
  100. {% for rule in rules %}
  101. <div>
  102. <h2 id="{{ rule['name'] }}">{{ rule['name'] }} ({{ rule['ip'] }})</h2>
  103. <form method="POST" action="{{ url_for('new_rule', interface=rule['name']) }}">
  104. <table class="pure-table">
  105. <thead>
  106. <tr>
  107. <th>Name</th>
  108. <th>Current Value</th>
  109. <th>New Value</th>
  110. <th>Variance / Correlation</th>
  111. <th>New Value</th>
  112. </tr>
  113. </thead>
  114. <tbody>
  115. <tr>
  116. <td>Rate</td>
  117. <td class="tcgui-value-cell">{{ rule['rate'] }}</td>
  118. <td class="tcgui-input-cell">
  119. <div class="input-group">
  120. <input type="number" name="Rate" size="5">
  121. <select name="rate_unit">
  122. {% for unit in units %}
  123. <option value="{{ unit }}" {% if unit == standard_unit %} selected{% endif %}>{{ unit }}</option>
  124. {% endfor %}
  125. </select>
  126. </div>
  127. </td>
  128. </tr>
  129. <tr>
  130. <td>Delay</td>
  131. <td class="tcgui-value-cell">{{ rule['delay'] }}</td>
  132. <td class="tcgui-input-cell"><input type="number" name="Delay" size="5"> ms</td>
  133. <td class="tcgui-value-cell">±{{ rule['delayVariance'] }}</td>
  134. <td class="tcgui-input-cell">±<input type="number" name="DelayVariance" size="5"> ms</td>
  135. </tr>
  136. <tr>
  137. <td>Loss</td>
  138. <td class="tcgui-value-cell">{{ rule['loss'] }}</td>
  139. <td class="tcgui-input-cell"><input type="number" name="Loss" size="5"> %</td>
  140. <td class="tcgui-value-cell">{{ rule['lossCorrelation'] }}</td>
  141. <td class="tcgui-input-cell"><input type="number" name="LossCorrelation" size="5"> %</td>
  142. </tr>
  143. <tr>
  144. <td>Duplicate</td>
  145. <td class="tcgui-value-cell">{{ rule['duplicate'] }}</td>
  146. <td class="tcgui-input-cell"><input type="number" name="Duplicate" size="5"> %</td>
  147. </tr>
  148. <tr>
  149. <td>Reorder</td>
  150. <td class="tcgui-value-cell">{{ rule['reorder'] }}</td>
  151. <td class="tcgui-input-cell"><input type="number" name="Reorder" size="5"> %</td>
  152. <td class="tcgui-value-cell">{{ rule['reorderCorrelation'] }}</td>
  153. <td class="tcgui-input-cell"><input type="number" name="ReorderCorrelation" size="5"> %</td>
  154. </tr>
  155. <tr>
  156. <td>Corrupt</td>
  157. <td class="tcgui-value-cell">{{ rule['corrupt'] }}</td>
  158. <td class="tcgui-input-cell"><input type="number" name="Corrupt" size="5"> %</td>
  159. </tr>
  160. <tr>
  161. <td>Limit</td>
  162. <td class="tcgui-value-cell">{{ rule['limit'] }}</td>
  163. <td class="tcgui-input-cell"><input type="number" name="Limit" size="5"></td>
  164. </tr>
  165. </tbody>
  166. </table>
  167. <div class="btn-container">
  168. <input class="pure-button pure-button-primary" type="submit" value="Apply {{ rule['name'] }} ({{ rule['ip'] }}) Rules">
  169. </div>
  170. </form>
  171. <form method="POST" action="{{ url_for('remove_rule', interface= rule['name']) }}">
  172. <div class="btn-container">
  173. <input class="button-remove pure-button" type="submit" value="Remove {{ rule['name'] }} ({{ rule['ip'] }}) Rules">
  174. </div>
  175. </form>
  176. </div>
  177. {% endfor %}
  178. </div>
  179. <script type="text/javascript">
  180. (function() {
  181. /** Get next sibling of specified node or element.
  182. *
  183. * @param {Node|HTMLElement} element Element to search for the next sibling.
  184. * @returns {HTMLElement|null} Next sibling, null it not exists.
  185. */
  186. function nextSiblingElement(element) {
  187. do {
  188. element = element.nextSibling;
  189. } while (element && element.nodeType !== Node.ELEMENT_NODE)
  190. return element;
  191. }
  192. /** Get first child of specified node or element.
  193. *
  194. * @param {Node|HTMLElement} element Element to search for the first child of.
  195. * @returns {HTMLElement|null} First child element, null if not exists.
  196. */
  197. function firstChildElement(element) {
  198. element = element.firstChild;
  199. if (element && element.nodeType !== Node.ELEMENT_NODE)
  200. element = nextSiblingElement(element)
  201. return element;
  202. }
  203. var x = document.getElementsByClassName("tcgui-value-cell");
  204. var i, inputCell, input, select, match;
  205. for (i = 0; i < x.length; i++) {
  206. if (x[i].innerHTML.indexOf("None") === -1) {
  207. x[i].className += " modified";
  208. inputCell = nextSiblingElement(x[i]);
  209. input = firstChildElement(inputCell);
  210. if (input.tagName === "INPUT") {
  211. // Match value cell innerText to extract integer value and optional units.
  212. match = x[i].innerText.match(/[^\d]*([\d.]+)([%bitpskmg]*)/i);
  213. // Set input field to integer value.
  214. input.value = parseInt(match[1]);
  215. // Units are specified.
  216. if (match[2]) {
  217. // Check if next to text field exists a select, if it exists set selected option to units.
  218. select = nextSiblingElement(input);
  219. if (select && select.tagName === "SELECT")
  220. select.value = match[2].toLowerCase();
  221. }
  222. }
  223. }
  224. }
  225. })();
  226. </script>
  227. </body>
  228. </html>