Detail.cshtml 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. @page
  2. @model Admin.Pages.Mail.DetailModel
  3. @using SharedKernel.Extensions
  4. @{
  5. ViewData["Title"] = "메일 상세";
  6. var data = Model.Data!;
  7. }
  8. <div class="container mail-detail">
  9. <h3>@ViewData["Title"]</h3>
  10. <hr />
  11. <partial name="_StatusMessage" />
  12. <details open>
  13. <summary class="fs-5 mb-3">기본 정보</summary>
  14. <div class="adm-section__body adm-section__body--flush">
  15. <table class="table table-bordered mb-0 mail-detail__meta">
  16. <colgroup>
  17. <col class="mail-detail__meta-key" />
  18. <col />
  19. </colgroup>
  20. <tbody>
  21. <tr>
  22. <th>ID</th>
  23. <td>@data.ID</td>
  24. </tr>
  25. <tr>
  26. <th>상태</th>
  27. <td>
  28. @switch (data.Status)
  29. {
  30. case 0:
  31. <span class="badge bg-secondary">대기</span>
  32. break;
  33. case 1:
  34. <span class="badge bg-info">처리 중</span>
  35. break;
  36. case 2:
  37. <span class="badge bg-success">발송 완료</span>
  38. break;
  39. case 3:
  40. <span class="badge bg-danger">실패</span>
  41. break;
  42. default:
  43. <span class="badge bg-dark">@data.StatusName</span>
  44. break;
  45. }
  46. </td>
  47. </tr>
  48. <tr>
  49. <th>수신자</th>
  50. <td>@data.ToAddress</td>
  51. </tr>
  52. <tr>
  53. <th>제목</th>
  54. <td>@data.Subject</td>
  55. </tr>
  56. <tr>
  57. <th>카테고리</th>
  58. <td>@(data.Category ?? "-")</td>
  59. </tr>
  60. <tr>
  61. <th>재시도</th>
  62. <td>@data.RetryCount / @data.MaxRetryCount (다음 시도: @data.NextRetryAt.GetDateAt())</td>
  63. </tr>
  64. <tr>
  65. <th>마지막 오류</th>
  66. <td>@(data.LastError ?? "-")</td>
  67. </tr>
  68. <tr>
  69. <th>등록 시각</th>
  70. <td>@data.CreatedAt.GetDateAt()</td>
  71. </tr>
  72. <tr>
  73. <th>처리 시각</th>
  74. <td>@(data.ProcessedAt.GetDateAt() ?? "-")</td>
  75. </tr>
  76. <tr>
  77. <th>실패 확정 시각</th>
  78. <td>@(data.FailedAt.GetDateAt() ?? "-")</td>
  79. </tr>
  80. </tbody>
  81. </table>
  82. </div>
  83. </details>
  84. <hr/>
  85. <br/>
  86. <details open>
  87. <summary class="fs-5 mb-3">
  88. HTML 본문 미리보기
  89. <small class="text-muted fw-normal">— sandbox iframe 으로 렌더링됩니다.</small>
  90. </summary>
  91. <div class="adm-section__body">
  92. <iframe id="mailPreview" sandbox="allow-same-origin" class="mail-detail__preview"></iframe>
  93. </div>
  94. </details>
  95. <hr/>
  96. <br/>
  97. @if (!string.IsNullOrWhiteSpace(data.MessageText))
  98. {
  99. <details>
  100. <summary class="fs-5 mb-3">텍스트 본문</summary>
  101. <div class="adm-section__body">
  102. <pre class="mail-detail__pre">@data.MessageText</pre>
  103. </div>
  104. </details>
  105. }
  106. <details>
  107. <summary class="fs-5 mb-3">HTML 원본</summary>
  108. <div class="adm-section__body">
  109. <pre class="mail-detail__pre mail-detail__pre--raw">@data.MessageHtml</pre>
  110. </div>
  111. </details>
  112. <hr/>
  113. <div class="d-flex gap-2 justify-content-center">
  114. <a href="/Mail/List" class="btn btn-secondary">목록</a>
  115. <form method="post" asp-page-handler="Resend" class="d-inline">
  116. @Html.AntiForgeryToken()
  117. <input type="hidden" name="id" value="@data.ID" />
  118. <button type="submit" class="btn btn-warning btn-detail-resend">재전송</button>
  119. </form>
  120. <form method="post" asp-page-handler="Delete" class="d-inline">
  121. @Html.AntiForgeryToken()
  122. <input type="hidden" name="id" value="@data.ID" />
  123. <button type="submit" class="btn btn-danger btn-detail-delete">삭제</button>
  124. </form>
  125. </div>
  126. <br/>
  127. <br/>
  128. <br />
  129. </div>
  130. @section Styles {
  131. <style>
  132. .mail-detail__meta-key {
  133. width: 15%;
  134. }
  135. .mail-detail__preview {
  136. width: 100%;
  137. height: 480px;
  138. border: 0;
  139. }
  140. .mail-detail__pre {
  141. margin: 0;
  142. white-space: pre-wrap;
  143. word-break: break-word;
  144. }
  145. .mail-detail__pre--raw {
  146. max-height: 300px;
  147. overflow: auto;
  148. }
  149. </style>
  150. }
  151. @section Scripts {
  152. <script>
  153. (function () {
  154. const src = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(data.MessageHtml));
  155. const iframe = document.getElementById("mailPreview");
  156. const doc = iframe.contentWindow.document;
  157. doc.open();
  158. doc.write(src);
  159. doc.close();
  160. })();
  161. $(document).on("click", ".btn-detail-resend", function (e) {
  162. if (!confirm("이 메일을 재전송하시겠습니까?")) {
  163. e.preventDefault();
  164. return false;
  165. }
  166. });
  167. $(document).on("click", ".btn-detail-delete", function (e) {
  168. if (!confirm("이 메일을 삭제하시겠습니까?")) {
  169. e.preventDefault();
  170. return false;
  171. }
  172. });
  173. </script>
  174. }