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