|
20 | 20 | <div class="queue-selector-container text-left" style="margin-top: 16px; margin-bottom: 16px"> |
21 | 21 | Loading queues... |
22 | 22 | </div> |
| 23 | + |
| 24 | + <p> |
| 25 | + <input type="checkbox" id="sns-subscribe-to-sqs-raw-delivery-checkbox" /> |
| 26 | + <label for="sns-subscribe-to-sqs-raw-delivery-checkbox">Raw message delivery</label> |
| 27 | + </p> |
23 | 28 |
|
24 | 29 | <div class="modal-buttons text-center"> |
25 | 30 | <button onclick="sns_CreateSubscription_Click()">Create subscription</button> |
|
77 | 82 | </tbody> |
78 | 83 | </table> |
79 | 84 |
|
80 | | -<div style="display: flex; align-items: center"> |
81 | | - <h2>Subscriptions</h2> |
82 | | - <div style="text-align: right; font-size: 1.5em; flex-grow: 1"> |
83 | | - <a no-href onclick="showWindow('sns-subscribe-to-sqs-modal')" class="gs-icon-stack initial-white neon-green"> |
84 | | - <i class="fa-solid fa-list-check" style="margin-right: 4px"></i> |
85 | | - <i class="bi bi-plus-circle-fill gs-icon-overlay stroked" style="color: #000000"></i> |
86 | | - </a> |
| 85 | +<div class="gs-tab-control"> |
| 86 | + <div class="gs-tab-container"> |
| 87 | + <div class="gs-tabitem selected" data-tabpage="sns-send">Send</div> |
| 88 | + <div class="gs-tabitem" data-tabpage="sns-subscriptions">Subscriptions</div> |
87 | 89 | </div> |
88 | | -</div> |
89 | 90 |
|
90 | | -<table class="gs-list padded autosize-all-cols-but-first"> |
91 | | - <thead> |
92 | | - <tr> |
93 | | - <th>Endpoint</th> |
94 | | - <th>Protocol</th> |
95 | | - <th>Owner</th> |
96 | | - <th>Actions</th> |
97 | | - </tr> |
98 | | - </thead> |
99 | | - <tbody> |
100 | | - @foreach(var subscription in Model.Subscriptions.OrderBy(s => s.Protocol).ThenBy(s => s.Endpoint)) |
| 91 | + <div id="sns-send" class="gs-tabpage selected"> |
| 92 | + @{ await Html.RenderPartialAsync("~/Pages/SQS/_MessageEditorPartial.cshtml", new SQSMessageEditorModel("sns-send-message-editor", "__snsSendMessageEditor", "__snsSendMessageTextEditor")); } |
| 93 | + </div> |
| 94 | + |
| 95 | + <div id="sns-subscriptions" class="gs-tabpage"> |
| 96 | + <div style="display: flex; align-items: center"> |
| 97 | + <h2>Subscriptions</h2> |
| 98 | + <div style="text-align: right; font-size: 1.5em; flex-grow: 1"> |
| 99 | + <a no-href onclick="showWindow('sns-subscribe-to-sqs-modal')" class="gs-icon-stack initial-white neon-green"> |
| 100 | + <i class="fa-solid fa-list-check" style="margin-right: 4px"></i> |
| 101 | + <i class="bi bi-plus-circle-fill gs-icon-overlay stroked" style="color: #000000"></i> |
| 102 | + </a> |
| 103 | + </div> |
| 104 | + </div> |
| 105 | + |
| 106 | + @if(Model.Subscriptions != null && Model.Subscriptions.Any()) |
101 | 107 | { |
102 | | - <tr data-arn="@subscription.Arn" data-endpoint="@subscription.Endpoint"> |
103 | | - @if(subscription.Protocol == null) |
104 | | - { |
105 | | - <td>@subscription.Endpoint</td> |
106 | | - } |
107 | | - else |
108 | | - { |
109 | | - <td> |
110 | | - @switch(subscription.Protocol.ToLower()) |
111 | | - { |
112 | | - case "sqs": |
113 | | - { |
114 | | - if (Arn.TryParse(subscription.Endpoint, out var arn)) |
| 108 | + <table class="gs-list padded autosize-all-cols-but-first"> |
| 109 | + <thead> |
| 110 | + <tr> |
| 111 | + <th>Endpoint</th> |
| 112 | + <th>Protocol</th> |
| 113 | + <th>Raw Delivery</th> |
| 114 | + <th>Owner</th> |
| 115 | + <th>Actions</th> |
| 116 | + </tr> |
| 117 | + </thead> |
| 118 | + <tbody> |
| 119 | + @foreach(var subscription in Model.Subscriptions.OrderBy(s => s.Protocol).ThenBy(s => s.Endpoint)) |
| 120 | + { |
| 121 | + <tr data-arn="@subscription.Arn" data-endpoint="@subscription.Endpoint"> |
| 122 | + <td> |
| 123 | + @switch(subscription.Protocol?.ToLower() ?? "") |
115 | 124 | { |
116 | | - <a href="/SQS/@arn.Resource"><i class="fa-solid fa-database gs-rotate-270" style="margin-right: 2px"></i> @arn.Resource</a> |
117 | | - } |
118 | | - else |
119 | | - { |
120 | | - <td>@subscription.Endpoint</td> |
| 125 | + case "sqs": |
| 126 | + { |
| 127 | + if(!Arn.TryParse(subscription.Endpoint, out var arn)) |
| 128 | + goto default; |
| 129 | + |
| 130 | + <a href="/SQS/@arn.Resource"><i class="fa-solid fa-database gs-rotate-270" style="margin-right: 2px"></i> @arn.Resource</a> |
| 131 | + break; |
| 132 | + } |
| 133 | + |
| 134 | + default: |
| 135 | + @subscription.Endpoint |
| 136 | + break; |
121 | 137 | } |
122 | | - break; |
123 | | - } |
124 | | - } |
125 | | - </td> |
126 | | - } |
127 | | - <td>@subscription.Protocol</td> |
128 | | - <td>@(!string.IsNullOrWhiteSpace(subscription.Owner) ? subscription.Owner : "(unknown)")</td> |
129 | | - <td> |
130 | | - <div class="gs-icons"> |
131 | | - <a no-href class="purple lnk-sns-sub-copyarn" title="Copy Endpoint address/ARN"> |
132 | | - <i class="fa-solid fa-link"></i> |
133 | | - </a> |
134 | | - <a no-href class="red lnk-sns-sub-delete" title="Delete"> |
135 | | - <i class="fa-solid fa-trash-can"></i> |
136 | | - </a> |
137 | | - </div> |
138 | | - </td> |
139 | | - </tr> |
| 138 | + </td> |
| 139 | + <td>@subscription.Protocol</td> |
| 140 | + <td>@(subscription.RawMessageDelivery ? "Yes" : "No")</td> |
| 141 | + <td>@(!string.IsNullOrWhiteSpace(subscription.Owner) ? subscription.Owner : "(unknown)")</td> |
| 142 | + <td> |
| 143 | + <div class="gs-icons"> |
| 144 | + <a no-href class="purple lnk-sns-sub-copyarn" title="Copy Endpoint address/ARN"> |
| 145 | + <i class="fa-solid fa-link"></i> |
| 146 | + </a> |
| 147 | + <a no-href class="red lnk-sns-sub-delete" title="Delete"> |
| 148 | + <i class="fa-solid fa-trash-can"></i> |
| 149 | + </a> |
| 150 | + </div> |
| 151 | + </td> |
| 152 | + </tr> |
| 153 | + } |
| 154 | + </tbody> |
| 155 | + </table> |
140 | 156 | } |
141 | | - </tbody> |
142 | | -</table> |
| 157 | + else |
| 158 | + { |
| 159 | + <text>No active subscriptions</text> |
| 160 | + } |
| 161 | + </div> |
| 162 | +</div> |
143 | 163 |
|
144 | 164 | <script type="text/javascript"> |
| 165 | + const SNS_URL_DELETE_SUBSCRIPTION = "@Url.Action("DeleteSubscription", "Subscriptions", new { subscriptionArn = "__SUBSCRIPTIONARN__" })"; |
| 166 | +
|
| 167 | + var prompt_SubscriptionArn; |
| 168 | +
|
| 169 | + var __snsSendLanguageSelect = __snsSendMessageEditor.querySelector(".lang-select"); |
| 170 | + var __snsSendButton = __snsSendMessageEditor.querySelector(".lnk-sqs-send"); |
| 171 | +
|
145 | 172 | var subscribeToSqsModal = document.getElementById("sns-subscribe-to-sqs-modal"); |
146 | 173 | var queueSelectorContainer = $("#sns-subscribe-to-sqs-modal .queue-selector-container"); |
147 | 174 |
|
| 175 | + __snsSendButton.addEventListener("click", sns_SendMessage_Click); |
| 176 | +
|
148 | 177 | $(".lnk-sns-sub-copyarn").click(sns_CopySubscriptionArn); |
149 | 178 | $(".lnk-sns-sub-delete").click(sns_DeleteSubscriptionPrompt); |
150 | 179 | $("#delete-sns-subscription-modal .yes-button").click(sns_DeleteSubscription); |
151 | 180 |
|
152 | | - const SNS_URL_DELETE_SUBSCRIPTION = "@Url.Action("DeleteSubscription", "Subscriptions", new { subscriptionArn = "__SUBSCRIPTIONARN__" })"; |
153 | | -
|
154 | | - var prompt_SubscriptionArn; |
155 | | -
|
156 | 181 | subscribeToSqsModal.addEventListener("windowopened", function() { |
157 | 182 | $.ajax({ |
158 | 183 | type: "GET", |
|
172 | 197 | queueSelectorContainer.html("Loading queues..."); |
173 | 198 | }); |
174 | 199 |
|
| 200 | + function sns_SendMessage_Click(event) |
| 201 | + { |
| 202 | + var lang = __snsSendLanguageSelect.value; |
| 203 | + var data = __snsSendMessageTextEditor.getValue(); |
| 204 | + var isProtobuf = (lang == "protojson"); |
| 205 | + var base64Encode = __snsSendMessageEditor.querySelector(".sqs-send-as-base64").checked; |
| 206 | +
|
| 207 | + if(isProtobuf) |
| 208 | + { |
| 209 | + try |
| 210 | + { |
| 211 | + var protoPath = __snsSendMessageEditor.getAttribute("data-selected-proto"); |
| 212 | +
|
| 213 | + if(isNull(protoPath) || protoPath.length <= 0) |
| 214 | + { |
| 215 | + gs_DisplayError("No Protobuf definition selected"); |
| 216 | + return; |
| 217 | + } |
| 218 | +
|
| 219 | + var protoRoot = gs_GetProtobufRootDefinition(protoPath); |
| 220 | + var protoType = protoPath |
| 221 | + .replace(/^proto\/[^\/]+\/?/, "") |
| 222 | + .replace("/", "."); |
| 223 | +
|
| 224 | + if(protoType.length <= 0) |
| 225 | + throw "'" + protoPath + "' is not a valid protobuf definition path: Path is too short"; |
| 226 | +
|
| 227 | + var root = protobuf.Root.fromJSON(JSON.parse(protoRoot)); |
| 228 | + var type = root.lookupType(protoType); |
| 229 | + var payload = JSON.parse(data); |
| 230 | + var message = type.fromObject(payload); |
| 231 | +
|
| 232 | + data = gs_Uint8ArrayToBase64(type.encode(message).finish()); |
| 233 | + } |
| 234 | + catch(error) |
| 235 | + { |
| 236 | + gs_DisplayError("An error occurred while constructing the Protobuf message: " + error); |
| 237 | + return; |
| 238 | + } |
| 239 | + } |
| 240 | +
|
| 241 | + $.ajax({ |
| 242 | + type: "POST", |
| 243 | + url: "@Url.Action("SendMessage", "Topics", new { topicArn = Model.Topic.TopicARN.ToString() ?? "" })", |
| 244 | + contentType: "application/json", |
| 245 | + data: JSON.stringify({ |
| 246 | + body: data, |
| 247 | + isProtobuf: isProtobuf, |
| 248 | + base64Encode: base64Encode |
| 249 | + }), |
| 250 | + error: gsevent_AjaxError, |
| 251 | + success: function(result) { |
| 252 | + __snsSendMessageTextEditor.setValue(""); |
| 253 | + } |
| 254 | + }); |
| 255 | + } |
| 256 | +
|
175 | 257 | async function sns_CreateSubscription_Click() |
176 | 258 | { |
177 | 259 | var selectedItem = gs_GetSelectedTableItem(queueSelectorContainer[0]); |
|
183 | 265 | } |
184 | 266 |
|
185 | 267 | var queueUrl = selectedItem.getAttribute("data-url"); |
| 268 | + var rawMessageDelivery = document.getElementById("sns-subscribe-to-sqs-raw-delivery-checkbox").checked; |
186 | 269 |
|
187 | 270 | try |
188 | 271 | { |
|
192 | 275 | body: JSON.stringify({ |
193 | 276 | topicArn: "@Model.Topic.TopicARN", |
194 | 277 | protocol: "sqs", |
195 | | - endpoint: queueUrl |
| 278 | + endpoint: queueUrl, |
| 279 | + rawMessageDelivery: rawMessageDelivery |
196 | 280 | }) |
197 | 281 | }); |
198 | 282 |
|
|
0 commit comments