PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/BlogEngine/BlogEngine.NET/admin/Blogs.aspx

#
ASP.NET | 407 lines | 326 code | 81 blank | 0 comment | 36 complexity | 2c69ac363b663d07fd0ade63754c07a1 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
  1. <%@ Page Title="" Language="C#" MasterPageFile="~/admin/admin.master" AutoEventWireup="true" CodeFile="Blogs.aspx.cs" Inherits="Admin.Blogs" %>
  2. <%@ Import Namespace="BlogEngine.Core" %>
  3. <asp:Content ID="Content1" ContentPlaceHolderID="cphAdmin" runat="Server">
  4. <script type="text/javascript" src="jquery.colorbox.js"></script>
  5. <script type="text/javascript" src="jquery.tipsy.js"></script>
  6. <script type="text/javascript">
  7. function GetBlogDataJson() {
  8. // note: blogId might be empty if this is a new blog being added.
  9. var data = {
  10. "blogId": $.trim($('#hdnEditBlogId').val()),
  11. "copyFromExistingBlogId": $.trim($('#existingBlogToCreateNewBlogFrom').val()),
  12. "blogName": $.trim($('#txtBlogName').val()),
  13. "storageContainerName": $.trim($('#txtStorageContainerName').val()),
  14. "hostname": $.trim($('#txtHostname').val()),
  15. "isAnyTextBeforeHostnameAccepted": $('#cbAcceptAnyTextBeforeHostname').is(':checked'),
  16. "virtualPath": $.trim($('#txtVirtualPath').val()),
  17. "isActive": $('#cbActive').is(':checked')
  18. };
  19. return data;
  20. }
  21. function IsValidChars(value) {
  22. return /^[a-z0-9-_]+$/i.test(value);
  23. }
  24. function OnlyAllowedMsg() {
  25. return "Only letters, numbers, hyphens and underscores are allowed.";
  26. }
  27. var validIpAddressRegex = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/i;
  28. var validHostnameRegex = /^(([a-z]|[a-z][a-z0-9\-]*[a-z0-9])\.)*([a-z]|[a-z][a-z0-9\-]*[a-z0-9])$/i;
  29. function IsEditingPrimary() {
  30. }
  31. function IsBlogDataValid() {
  32. // hide all validators.
  33. $('.overlaypanel req').addClass('hidden');
  34. var data = GetBlogDataJson();
  35. if (data.blogName.length === 0) {
  36. $('#txtBlogNameReq').removeClass('hidden');
  37. $('#txtUserName').focus().select();
  38. return false;
  39. }
  40. var storageContainerNameIsReadonly = $('#txtStorageContainerName').attr('readonly');
  41. if (!storageContainerNameIsReadonly) {
  42. if (data.storageContainerName.length === 0) {
  43. $('#txtStorageContainerNameReq').removeClass('hidden');
  44. $('#txtStorageContainerName').focus().select();
  45. return false;
  46. } else {
  47. if (!IsValidChars(data.storageContainerName)) {
  48. $('#txtStorageContainerNameReq').removeClass('hidden');
  49. $('#txtStorageContainerName').focus().select();
  50. alert('The Storage Container Name contains invalid characters. ' + OnlyAllowedMsg());
  51. return false;
  52. }
  53. }
  54. }
  55. if (data.hostname.length > 0) {
  56. if (!validIpAddressRegex.test(data.hostname) &&
  57. !validHostnameRegex.test(data.hostname)) {
  58. $('#txtHostnameInvalid').removeClass('hidden');
  59. $('#txtHostname').focus().select();
  60. alert('Host name is invalid. It should contain either an IP address or domain name, e.g. example.com');
  61. return false;
  62. }
  63. }
  64. if (data.virtualPath.length === 0) {
  65. $('#txtVirtualPathReq').removeClass('hidden');
  66. $('#txtVirtualPath').focus().select();
  67. return false;
  68. } else {
  69. if (data.virtualPath.indexOf('~/') !== 0) {
  70. $('#txtVirtualPathReq').removeClass('hidden');
  71. $('#txtVirtualPath').focus().select();
  72. alert('Virtual path must begin with ~/\n\nPlease add ~/ to the beginning of your virtual path.');
  73. return false;
  74. }
  75. // note: a virtual path of ~/ without anything after it is allowed. this would
  76. // typically be for the primary blog, but can also be for blogs that are using
  77. // subdomains, where each instance might be ~/
  78. var vpath = data.virtualPath.substr(2);
  79. if (vpath.length > 0) {
  80. if (!IsValidChars(vpath)) {
  81. $('#txtVirtualPathReq').removeClass('hidden');
  82. $('#txtVirtualPath').focus().select();
  83. alert('The Virtual Path after ~/ contains invalid characters. ' + OnlyAllowedMsg());
  84. return false;
  85. }
  86. }
  87. }
  88. // if this is a new blog...
  89. if (!data.blogId) {
  90. if (!data.copyFromExistingBlogId) {
  91. $('#existingBlogToCreateNewBlogFrom').focus()
  92. alert('An existing blog to create the new blog from must be selected.');
  93. return false;
  94. }
  95. }
  96. return true;
  97. }
  98. function BlogDataReceived(data) {
  99. if (!data.Success) {
  100. ShowStatus("warning", "Unable to retrieve the blog data to edit. Message: " + (data.Message || "(none)"));
  101. return;
  102. }
  103. resetForm();
  104. $('#newBlogData').hide();
  105. $('#addNewBlogHeader').hide();
  106. $('#editBlogHeader').show();
  107. data = data.Data;
  108. $('#hdnEditBlogId').val(data.Id);
  109. $('#txtBlogName').val(data.Name);
  110. $('#txtStorageContainerName').val(data.StorageContainerName).attr('readonly', 'readonly').css('background-color', '#d8d8d8').css('color', '#787878');
  111. $('#txtHostname').val(data.Hostname);
  112. $('#txtVirtualPath').val(data.VirtualPath);
  113. SetCheckbox($('#cbAcceptAnyTextBeforeHostname'), data.IsAnyTextBeforeHostnameAccepted);
  114. SetCheckbox($('#cbActive'), data.IsActive);
  115. OpenColorbox();
  116. }
  117. function SetCheckbox(cb, isChecked) {
  118. if (isChecked) {
  119. cb.attr('checked', 'checked');
  120. } else {
  121. cb.removeAttr('checked');
  122. }
  123. }
  124. function EditBlog(btn) {
  125. var row = $(btn).closest('tr');
  126. var id = row.attr('id');
  127. if (!id || id.length !== 36) {
  128. ShowStatus("warning", "Sorry, cannot determine the ID of the Blog you would like to edit.");
  129. return false;
  130. }
  131. GetBlog(id, BlogDataReceived);
  132. return false;
  133. }
  134. function SaveBlog() {
  135. // this same SaveBlog() is called for both Adding and Updating blogs.
  136. if (!IsBlogDataValid()) {
  137. return;
  138. }
  139. var data = GetBlogDataJson();
  140. $.ajax({
  141. url: SiteVars.ApplicationRelativeWebRoot + "api/Blogs.asmx/SaveBlog",
  142. data: JSON.stringify(data),
  143. type: "POST",
  144. contentType: "application/json; charset=utf-8",
  145. dataType: "json",
  146. beforeSend: onAjaxBeforeSend,
  147. success: function (result) {
  148. var rt = result.d;
  149. if (rt.Success) {
  150. resetForm();
  151. LoadBlogs();
  152. ShowStatus("success", rt.Message);
  153. }
  154. else {
  155. ShowStatus("warning", rt.Message);
  156. }
  157. closeOverlay();
  158. },
  159. error: function (xhr, ajaxOptions, thrownError) {
  160. closeOverlay();
  161. ShowStatus("warning", "An unexpected error occurred: " + (thrownError || ""));
  162. }
  163. });
  164. return false;
  165. }
  166. function onAddNewClicked() {
  167. resetForm();
  168. $('#newBlogData').show();
  169. $('#addNewBlogHeader').show();
  170. $('#editBlogHeader').hide();
  171. $('#txtStorageContainerName').removeAttr('readonly').css('background-color', '').css('color', '');
  172. var copyFrom = $('#existingBlogToCreateNewBlogFrom');
  173. if ($('option', copyFrom).length > 0) {
  174. return true;
  175. } else {
  176. /* make a synchronous call to get the available blogs to copy from */
  177. $.ajax({
  178. url: SiteVars.ApplicationRelativeWebRoot + "admin/AjaxHelper.aspx/GetCopyFromBlogs",
  179. data: JSON.stringify({ }),
  180. type: "POST",
  181. async: false, /* note: this is synchronous */
  182. contentType: "application/json; charset=utf-8",
  183. dataType: "json",
  184. beforeSend: onAjaxBeforeSend,
  185. success: function (result) {
  186. var rt = result.d;
  187. if (rt.Success) {
  188. copyFrom.append($(document.createElement("option")).attr("value", "").text("Select One"));
  189. for (var i = 0; i < rt.Data.length; i++) {
  190. copyFrom.append($(document.createElement("option")).attr("value", rt.Data[i].Key).text(rt.Data[i].Value));
  191. }
  192. return true;
  193. }
  194. else {
  195. ShowStatus("warning", rt.Message);
  196. }
  197. },
  198. error: function (xhr, ajaxOptions, thrownError) {
  199. ShowStatus("warning", "An unexpected error occurred: " + (thrownError || ""));
  200. }
  201. });
  202. }
  203. return false;
  204. }
  205. function OnAdminDataSaved() {
  206. LoadBlogs();
  207. }
  208. function closeOverlay() {
  209. $.colorbox.close();
  210. }
  211. function resetForm() {
  212. $('.tblForm .req').addClass('hidden');
  213. $('#hdnEditBlogId').val('');
  214. $('#txtBlogName').val('');
  215. $('#txtStorageContainerName').val('');
  216. $('#txtHostname').val('');
  217. $('#cbAcceptAnyTextBeforeHostname').attr('checked', 'checked');
  218. $('#txtVirtualPath').val('');
  219. $('#cbActive').attr('checked', 'checked');
  220. }
  221. function OpenColorbox() {
  222. var colorboxOptions = GetColorboxOptions();
  223. colorboxOptions.open = true;
  224. $('<a/>').colorbox(colorboxOptions);
  225. }
  226. function GetColorboxOptions() {
  227. var opts = { width: "550px", inline: true, href: '#frmAddNew' };
  228. return opts;
  229. }
  230. $(function () {
  231. var colorboxOptions = GetColorboxOptions();
  232. colorboxOptions.onOpen = onAddNewClicked;
  233. $(".addNew").colorbox(colorboxOptions);
  234. LoadBlogsForPage(1);
  235. $(".tableToolBox a").click(function () {
  236. $(".tableToolBox a").removeClass("current");
  237. $(this).addClass("current");
  238. });
  239. $("#txtVirtualPath").focus(function () {
  240. if ($.trim($(this).val()).length === 0) {
  241. $(this).val('~/');
  242. }
  243. });
  244. });
  245. </script>
  246. <div style="display:none;">
  247. <div id="frmAddNew" class="overlaypanel" >
  248. <h2>
  249. <span id="addNewBlogHeader"><%=Resources.labels.addNewBlog%></span>
  250. <span id="editBlogHeader"><%=Resources.labels.editExistingBlog%></span>
  251. </h2>
  252. <input type="hidden" id="hdnEditBlogId" />
  253. <table class="tblForm">
  254. <tr>
  255. <td>
  256. <label for="txtBlogName" class="lbl"><%=Resources.labels.name %></label>
  257. <input type="text" id="txtBlogName" class="txt200"/>
  258. <span id="txtBlogNameReq" class="req hidden">*</span>
  259. </td>
  260. <td>
  261. <label for="txtStorageContainerName" class="lbl"><%=Resources.labels.storageContainerName%></label>
  262. <input type="text" id="txtStorageContainerName" class="txt200"/>
  263. <span id="txtStorageContainerNameReq" class="req hidden">*</span>
  264. </td>
  265. </tr>
  266. <tr>
  267. <td>
  268. <label for="txtHostname" class="lbl"><%=Resources.labels.hostName%></label>
  269. <input type="text" id="txtHostname" class="txt200"/>
  270. <span id="txtHostnameInvalid" class="req hidden">*</span>
  271. </td>
  272. <td>
  273. <label for="cbAcceptAnyTextBeforeHostname" class="lbl"><%=Resources.labels.acceptAnyTextBeforeHostname%></label>
  274. <input type="checkbox" id="cbAcceptAnyTextBeforeHostname" />
  275. </td>
  276. </tr>
  277. <tr>
  278. <td>
  279. <label for="txtVirtualPath" class="lbl"><%=Resources.labels.virtualPath %></label>
  280. <input type="text" id="txtVirtualPath" class="txt200"/>
  281. <span id="txtVirtualPathReq" class="req hidden">*</span>
  282. </td>
  283. <td>
  284. <label for="cbActive" class="lbl"><%=Resources.labels.active %></label>
  285. <input type="checkbox" id="cbActive"/>
  286. </td>
  287. </tr>
  288. </table>
  289. <div id="newBlogData" style="margin:0 0 20px;">
  290. <h2><%=Resources.labels.existingBlogToCreateNewBlogFrom %></h2>
  291. <select id="existingBlogToCreateNewBlogFrom"></select>
  292. </div>
  293. <input type="submit" class="btn primary rounded" value="<%=Resources.labels.save %>" onclick="return SaveBlog();" id="btnNewBlog" />
  294. <%=Resources.labels.or %> <a href="#" onclick="closeOverlay();"><%=Resources.labels.cancel %></a>
  295. <br /><br />
  296. </div>
  297. </div>
  298. <div class="content-box-outer">
  299. <div class="content-widgets-box-full">
  300. <h1><%=Resources.labels.blogs%><a href="#" class="addNew"><%=Resources.labels.addNewBlog%></a></h1>
  301. <div class="tableToolBox">
  302. <div class="Pager"></div>
  303. <div class="PageSize">
  304. <label for="pageSizeTop"><%=Resources.labels.itemsPerPage%></label>
  305. <select id="pageSizeTop" name="pageSizeTop" onchange="return ChangeBlogsPage(this)">
  306. <option value="10">10</option>
  307. <option value="25" selected="selected">25</option>
  308. <option value="50">50</option>
  309. <option value="100">100</option>
  310. </select>
  311. </div>
  312. </div>
  313. <div id="Container"></div>
  314. <div class="Pager"></div>
  315. <div class="PageSize">
  316. <label for="pageSizeBottom"><%=Resources.labels.itemsPerPage%></label>
  317. <select id="pageSizeBottom" name="pageSizeBottom" onchange="return ChangeBlogsPage(this)">
  318. <option value="10">10</option>
  319. <option value="25" selected="selected">25</option>
  320. <option value="50">50</option>
  321. <option value="100">100</option>
  322. </select>
  323. </div>
  324. </div>
  325. </div>
  326. </asp:Content>