dev-mailbox.html 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Vendure Development Inbox</title>
  6. <style>
  7. body {
  8. display: flex;
  9. flex-direction: column;
  10. height: 100vh;
  11. margin: 0;
  12. font-family: Helvetica, Arial, sans-serif;
  13. }
  14. .top-bar {
  15. padding: 12px;
  16. display: flex;
  17. align-items: center;
  18. background-color: #2a2929;
  19. color: #efefef;
  20. }
  21. .heading {
  22. margin: 0;
  23. }
  24. button#refresh {
  25. margin-left: 12px;
  26. border-radius: 3px;
  27. padding: 3px 6px;
  28. display: flex;
  29. align-items: center;
  30. }
  31. button#refresh .label {
  32. margin-left: 6px;
  33. font-size: 16px;
  34. }
  35. .generate-controls {
  36. flex: 1;
  37. display: flex;
  38. justify-content: flex-end;
  39. }
  40. input, select, button {
  41. padding: 6px;
  42. border-radius: 3px;
  43. border: 1px solid #15a9df;
  44. margin-left: 3px;
  45. }
  46. #language-code {
  47. width: 32px;
  48. }
  49. .content {
  50. display: flex;
  51. flex: 1;
  52. height: calc(100% - 60px);
  53. }
  54. .list {
  55. width: 40vw;
  56. min-width: 300px;
  57. padding: 6px;
  58. overflow: auto;
  59. }
  60. .row {
  61. border-bottom: 1px dashed #ddd;
  62. padding: 12px 6px;
  63. cursor: pointer;
  64. transition: background-color 0.2s;
  65. }
  66. .row:hover {
  67. background-color: #efefef;
  68. }
  69. .meta {
  70. display: flex;
  71. justify-content: space-between;
  72. color: #666;
  73. }
  74. .detail {
  75. flex: 1;
  76. border: 1px solid #999;
  77. display: flex;
  78. flex-direction: column;
  79. }
  80. .detail iframe {
  81. height: 100%;
  82. border: 1px solid #eee;
  83. overflow: auto;
  84. }
  85. .metadata {
  86. margin: 6px;
  87. }
  88. </style>
  89. </head>
  90. <body>
  91. <div class="top-bar">
  92. <h1 class="heading">Vendure Dev Mailbox</h1>
  93. <div>
  94. <button id="refresh">
  95. <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 36 36" preserveAspectRatio="xMidYMid meet" focusable="false" aria-hidden="true" role="img" width="16" height="16" fill="currentColor"><path class="clr-i-outline clr-i-outline-path-1" d="M32.84,15.72a1,1,0,1,0-2,.29A13.15,13.15,0,0,1,31,17.94,13,13,0,0,1,8.7,27h5.36a1,1,0,0,0,0-2h-9v9a1,1,0,1,0,2,0V28.2A15,15,0,0,0,32.84,15.72Z"/><path class="clr-i-outline clr-i-outline-path-2" d="M30.06,1A1.05,1.05,0,0,0,29,2V7.83A14.94,14.94,0,0,0,3,17.94a15.16,15.16,0,0,0,.2,2.48,1,1,0,0,0,1,.84h.16a1,1,0,0,0,.82-1.15A13.23,13.23,0,0,1,5,17.94a13,13,0,0,1,13-13A12.87,12.87,0,0,1,27.44,9H22.06a1,1,0,0,0,0,2H31V2A1,1,0,0,0,30.06,1Z"/></svg>
  96. <span class="label">Refresh</span>
  97. </button>
  98. </div>
  99. <div class="generate-controls">
  100. <select id="type-selector"></select>
  101. <input id="language-code" value="en" type="text">
  102. <button id="generate-test">Generate test</button>
  103. </div>
  104. </div>
  105. <div class="content">
  106. <div class="list">
  107. </div>
  108. <div class="detail">
  109. </div>
  110. </div>
  111. <script>
  112. const refreshButton = document.querySelector('button#refresh');
  113. refreshButton.addEventListener('click', refreshInbox);
  114. const typeSelect = document.querySelector('#type-selector');
  115. fetch('./types')
  116. .then(res => res.json())
  117. .then(res => {
  118. res.forEach(type => {
  119. const option = document.createElement('option');
  120. option.value = type;
  121. option.text = type;
  122. typeSelect.appendChild(option);
  123. });
  124. });
  125. const languageCodeInput = document.querySelector('#language-code');
  126. const generateTestButton = document.querySelector('#generate-test');
  127. generateTestButton.addEventListener('click', e => {
  128. fetch(`./generate/${typeSelect.value}/${languageCodeInput.value}`)
  129. .then(() => new Promise(resolve => setTimeout(resolve, 500)))
  130. .then(() => refreshInbox());
  131. });
  132. const list = document.querySelector('.list');
  133. refreshInbox();
  134. function refreshInbox() {
  135. fetch('./list')
  136. .then(res => res.json())
  137. .then(res => renderList(res));
  138. }
  139. function renderList(items) {
  140. const list = document.querySelector('.list');
  141. list.innerHTML = '';
  142. const rows = items.forEach(item => {
  143. const row = document.createElement('div');
  144. row.classList.add('row');
  145. row.innerHTML = `
  146. <div class="meta">
  147. <div class="date">${item.date}</div>
  148. <div class="recipient">${item.recipient}</div>
  149. </div>
  150. <div class="subject">${item.subject}</div>`;
  151. row.addEventListener('click', (e) => {
  152. fetch('./item/' + item.fileName)
  153. .then(res => res.json())
  154. .then(res => renderEmail(res));
  155. });
  156. list.appendChild(row);
  157. });
  158. }
  159. function renderEmail(email) {
  160. const content = `
  161. <div class="metadata">
  162. <table>
  163. <tr>
  164. <td>Recipient:</td>
  165. <td>${email.recipient}</td>
  166. </tr>
  167. <tr>
  168. <td>Subject:</td>
  169. <td>${email.subject}</td>
  170. </tr>
  171. <tr>
  172. <td>Date:</td>
  173. <td>${new Date().toLocaleString()}</td>
  174. </tr>
  175. </table>
  176. </div>
  177. <iframe srcdoc="${email.body.replace(/"/g, '&quot;')}"></iframe>
  178. `;
  179. document.querySelector('.detail').innerHTML = content;
  180. }
  181. </script>
  182. </body>
  183. </html>