Fixes: #U4-2312 - Moving content with the new API (and in the old api when calling library.UpdateDocumentCache(p.Id)) The document is actually moved properly in the content XML structure without republishing it and then rebuilding the entire XML structure, it just does it inline. Have also updated MoveAndCopy.aspx dialog to use the new API which now saves on about 20+ queries that were not needed. Also updated the MoveAndCopy dialog to have the correct code behind structure.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
@@ -14,11 +15,56 @@ using Umbraco.Core.Media;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public static class ContentExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the IContentBase has children
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is a bit of a hack because we need to type check!
|
||||
/// </remarks>
|
||||
internal static bool HasChildren(IContentBase content, ServiceContext services)
|
||||
{
|
||||
if (content is IContent)
|
||||
{
|
||||
return services.ContentService.HasChildren(content.Id);
|
||||
}
|
||||
if (content is IMedia)
|
||||
{
|
||||
return services.MediaService.HasChildren(content.Id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the children for the content base item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is a bit of a hack because we need to type check!
|
||||
/// </remarks>
|
||||
internal static IEnumerable<IContentBase> Children(IContentBase content, ServiceContext services)
|
||||
{
|
||||
if (content is IContent)
|
||||
{
|
||||
return services.ContentService.GetChildren(content.Id);
|
||||
}
|
||||
if (content is IMedia)
|
||||
{
|
||||
return services.MediaService.GetChildren(content.Id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set property values by alias with an annonymous object
|
||||
/// </summary>
|
||||
|
||||
@@ -696,7 +696,6 @@
|
||||
<Compile Include="Xml\DynamicContext.cs" />
|
||||
<Compile Include="Xml\XmlNamespaces.cs" />
|
||||
<Compile Include="Xml\XmlNodeListFactory.cs" />
|
||||
<Compile Include="Xml\XmlNodeExtensions.cs" />
|
||||
<Compile Include="Xml\XPathVariable.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
// source: mvpxml.codeplex.com
|
||||
|
||||
namespace Umbraco.Core.Xml
|
||||
{
|
||||
internal static class XmlNodeExtensions
|
||||
{
|
||||
static XPathNodeIterator Select(string expression, XPathNavigator source, params XPathVariable[] variables)
|
||||
{
|
||||
var expr = source.Compile(expression);
|
||||
var context = new DynamicContext();
|
||||
foreach (var variable in variables)
|
||||
context.AddVariable(variable.Name, variable.Value);
|
||||
expr.SetContext(context);
|
||||
return source.Select(expr);
|
||||
}
|
||||
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectNodes(source, expression, av);
|
||||
}
|
||||
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectNodes(expression);
|
||||
|
||||
var iterator = Select(expression, source.CreateNavigator(), variables);
|
||||
return XmlNodeListFactory.CreateNodeList(iterator);
|
||||
}
|
||||
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectSingleNode(source, expression, av);
|
||||
}
|
||||
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectSingleNode(expression);
|
||||
|
||||
return SelectNodes(source, expression, variables).Cast<XmlNode>().FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core.Xml;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -9,6 +13,45 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
internal static class XmlExtensions
|
||||
{
|
||||
static XPathNodeIterator Select(string expression, XPathNavigator source, params XPathVariable[] variables)
|
||||
{
|
||||
var expr = source.Compile(expression);
|
||||
var context = new DynamicContext();
|
||||
foreach (var variable in variables)
|
||||
context.AddVariable(variable.Name, variable.Value);
|
||||
expr.SetContext(context);
|
||||
return source.Select(expr);
|
||||
}
|
||||
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectNodes(source, expression, av);
|
||||
}
|
||||
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectNodes(expression);
|
||||
|
||||
var iterator = Select(expression, source.CreateNavigator(), variables);
|
||||
return XmlNodeListFactory.CreateNodeList(iterator);
|
||||
}
|
||||
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectSingleNode(source, expression, av);
|
||||
}
|
||||
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectSingleNode(expression);
|
||||
|
||||
return SelectNodes(source, expression, variables).Cast<XmlNode>().FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts from an XDocument to an XmlDocument
|
||||
/// </summary>
|
||||
|
||||
@@ -334,6 +334,13 @@
|
||||
<DependentUpon>EditMacro.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Umbraco\Dialogs\MoveOrCopy.aspx.cs">
|
||||
<DependentUpon>moveOrCopy.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Umbraco\Dialogs\MoveOrCopy.aspx.designer.cs">
|
||||
<DependentUpon>moveOrCopy.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Umbraco\dialogs\Sort.aspx.cs">
|
||||
<DependentUpon>sort.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
@@ -2353,7 +2360,9 @@
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<Content Include="Config\404handlers.config" />
|
||||
<Content Include="Config\Dashboard.config" />
|
||||
<Content Include="Config\Dashboard.config">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
<Content Include="Config\metablogConfig.config" />
|
||||
<Content Include="Config\restExtensions.config">
|
||||
<SubType>Designer</SubType>
|
||||
|
||||
@@ -10,7 +10,7 @@ NOTES:
|
||||
* Compression/Combination/Minification is not enabled unless debug="false" is specified on the 'compiliation' element in the web.config
|
||||
* A new version will invalidate both client and server cache and create new persisted files
|
||||
-->
|
||||
<clientDependency version="5" fileDependencyExtensions=".js,.css">
|
||||
<clientDependency version="6" fileDependencyExtensions=".js,.css">
|
||||
|
||||
<fileRegistration defaultProvider="LoaderControlProvider">
|
||||
<providers>
|
||||
|
||||
@@ -100,4 +100,12 @@
|
||||
<control>/umbraco/plugins/uGoLive/Dashboard.ascx</control>
|
||||
</tab>
|
||||
</section>
|
||||
<section alias="Test Dashboard">
|
||||
<areas>
|
||||
<area>developer</area>
|
||||
</areas>
|
||||
<tab caption="Test Dashboard">
|
||||
<control>/UserControls/DashboardTest.ascx</control>
|
||||
</tab>
|
||||
</section>
|
||||
</dashBoard>
|
||||
11
src/Umbraco.Web.UI/umbraco/dialogs/MoveOrCopy.aspx.cs
Normal file
11
src/Umbraco.Web.UI/umbraco/dialogs/MoveOrCopy.aspx.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Web.UI.Umbraco.Dialogs
|
||||
{
|
||||
public partial class MoveOrCopy : global::umbraco.dialogs.moveOrCopy
|
||||
{
|
||||
}
|
||||
}
|
||||
15
src/Umbraco.Web.UI/umbraco/dialogs/MoveOrCopy.aspx.designer.cs
generated
Normal file
15
src/Umbraco.Web.UI/umbraco/dialogs/MoveOrCopy.aspx.designer.cs
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Umbraco.Web.UI.Umbraco.Dialogs {
|
||||
|
||||
|
||||
public partial class MoveOrCopy {
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<%@ Page Language="c#" CodeBehind="moveOrCopy.aspx.cs" MasterPageFile="../masterpages/umbracoDialog.Master" AutoEventWireup="True" Inherits="umbraco.dialogs.moveOrCopy" %>
|
||||
<%@ Page Language="c#" CodeBehind="moveOrCopy.aspx.cs" MasterPageFile="../masterpages/umbracoDialog.Master" AutoEventWireup="True" Inherits="Umbraco.Web.UI.Umbraco.Dialogs.MoveOrCopy" %>
|
||||
<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %>
|
||||
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
<%@ Register Src="../controls/Tree/TreeControl.ascx" TagName="TreeControl" TagPrefix="umbraco" %>
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Xml;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Routing;
|
||||
using umbraco;
|
||||
using umbraco.NodeFactory;
|
||||
|
||||
@@ -367,6 +367,9 @@
|
||||
<Compile Include="umbraco.presentation\umbraco\controls\ContentTypeControlNew.ascx.cs">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="umbraco.presentation\umbraco\dialogs\moveOrCopy.aspx.cs">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="umbraco.presentation\umbraco\dialogs\sort.aspx.cs">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
@@ -1247,13 +1250,6 @@
|
||||
<Compile Include="umbraco.presentation\umbraco\dialogs\insertTable.aspx.designer.cs">
|
||||
<DependentUpon>insertTable.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="umbraco.presentation\umbraco\dialogs\moveOrCopy.aspx.cs">
|
||||
<DependentUpon>moveOrCopy.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="umbraco.presentation\umbraco\dialogs\moveOrCopy.aspx.designer.cs">
|
||||
<DependentUpon>moveOrCopy.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="umbraco.presentation\umbraco\dialogs\notifications.aspx.cs">
|
||||
<DependentUpon>notifications.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
@@ -1920,7 +1916,6 @@
|
||||
<Content Include="umbraco.presentation\umbraco\dialogs\importDocumenttype.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\dialogs\insertMacro.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\dialogs\insertTable.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\dialogs\moveOrCopy.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\dialogs\notifications.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\developer\Packages\installer.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\dialogs\protectPage.aspx" />
|
||||
|
||||
@@ -415,7 +415,24 @@ namespace umbraco
|
||||
}
|
||||
else
|
||||
{
|
||||
//check the current parent id
|
||||
var currParentId = currentNode.AttributeValue<int>("parentID");
|
||||
|
||||
//update the node with it's new values
|
||||
TransferValuesFromDocumentXmlToPublishedXml(docNode, currentNode);
|
||||
|
||||
//If the node is being moved we also need to ensure that it exists under the new parent!
|
||||
// http://issues.umbraco.org/issue/U4-2312
|
||||
// we were never checking this before and instead simply changing the parentId value but not
|
||||
// changing the actual parent.
|
||||
|
||||
//check the new parent
|
||||
if (currParentId != currentNode.AttributeValue<int>("parentID"))
|
||||
{
|
||||
//ok, we've actually got to move the node
|
||||
parentNode.AppendChild(currentNode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: Update with new schema!
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
<%@ Page Language="c#" CodeBehind="moveOrCopy.aspx.cs" MasterPageFile="../masterpages/umbracoDialog.Master" AutoEventWireup="True" Inherits="umbraco.dialogs.moveOrCopy" %>
|
||||
<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %>
|
||||
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
<%@ Register Src="../controls/Tree/TreeControl.ascx" TagName="TreeControl" TagPrefix="umbraco" %>
|
||||
|
||||
<asp:Content ContentPlaceHolderID="head" runat="server">
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function dialogHandler(id) {
|
||||
document.getElementById("copyTo").value = id;
|
||||
document.getElementById("<%= ok.ClientID %>").disabled = false;
|
||||
|
||||
// Get node name by xmlrequest
|
||||
if (id > 0)
|
||||
umbraco.presentation.webservices.CMSNode.GetNodeName('<%=umbraco.BasePages.BasePage.umbracoUserContextID%>', id, updateName);
|
||||
else{
|
||||
//document.getElementById("pageNameContent").innerHTML = "'<strong><%=umbraco.ui.Text(umbraco.helper.Request("app"))%></strong>' <%= umbraco.ui.Text("moveOrCopy","nodeSelected") %>";
|
||||
|
||||
jQuery("#pageNameContent").html("<strong><%=umbraco.ui.Text(umbraco.helper.Request("app"))%></strong> <%= umbraco.ui.Text("moveOrCopy","nodeSelected") %>");
|
||||
jQuery("#pageNameHolder").attr("class","success");
|
||||
}
|
||||
}
|
||||
|
||||
var actionIsValid = true;
|
||||
|
||||
function updateName(result) {
|
||||
if(actionIsValid)
|
||||
{
|
||||
jQuery("#pageNameContent").html("'<strong>" + result + "</strong>' <%= umbraco.ui.Text("moveOrCopy","nodeSelected") %>");
|
||||
jQuery("#pageNameHolder").attr("class","success");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function notValid()
|
||||
{
|
||||
jQuery("#pageNameHolder").attr("class", "error");
|
||||
jQuery("#pageNameContent").html("<%= umbraco.ui.Text("moveOrCopy","notValid") %>");
|
||||
actionIsValid = false;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<style type="text/css">
|
||||
.propertyItemheader
|
||||
{
|
||||
width: 180px !important;
|
||||
}
|
||||
</style>
|
||||
</asp:Content>
|
||||
<asp:Content ContentPlaceHolderID="body" runat="server">
|
||||
<umb:JsInclude ID="JsInclude1" runat="server" FilePath="js/umbracoCheckKeys.js" PathNameAlias="UmbracoRoot"/>
|
||||
|
||||
<input type="hidden" id="copyTo" name="copyTo" />
|
||||
<cc1:Feedback ID="feedback" runat="server" />
|
||||
<cc1:Pane ID="pane_form" runat="server" Visible="false">
|
||||
<cc1:PropertyPanel runat="server" Style="overflow: auto; height: 220px;position: relative;">
|
||||
<umbraco:TreeControl runat="server" ID="JTree" App='<%#umbraco.helper.Request("app") %>'
|
||||
IsDialog="true" DialogMode="id" ShowContextMenu="false" FunctionToCall="dialogHandler"
|
||||
Height="200"></umbraco:TreeControl>
|
||||
</cc1:PropertyPanel>
|
||||
<cc1:PropertyPanel runat="server" ID="pp_relate" Text="relateToOriginal">
|
||||
<asp:CheckBox runat="server" ID="RelateDocuments" Checked="false" />
|
||||
</cc1:PropertyPanel>
|
||||
</cc1:Pane>
|
||||
<asp:PlaceHolder ID="pane_form_notice" runat="server" Visible="false">
|
||||
<div class="notice" id="pageNameHolder" style="margin-top: 10px;">
|
||||
<p id="pageNameContent">
|
||||
<%= umbraco.ui.Text("moveOrCopy","noNodeSelected") %></p>
|
||||
</div>
|
||||
</asp:PlaceHolder>
|
||||
<cc1:Pane ID="pane_settings" runat="server" Visible="false">
|
||||
<cc1:PropertyPanel ID="PropertyPanel1" runat="server" Text="Master Document Type">
|
||||
<asp:ListBox ID="masterType" runat="server" CssClass="bigInput" Rows="1" SelectionMode="Single"></asp:ListBox>
|
||||
</cc1:PropertyPanel>
|
||||
<cc1:PropertyPanel runat="server" Text="Name">
|
||||
<asp:TextBox ID="rename" runat="server" Style="width: 350px;" CssClass="bigInput"></asp:TextBox><asp:RequiredFieldValidator ID="RequiredFieldValidator1" ErrorMessage="*" ControlToValidate="rename" runat="server">*</asp:RequiredFieldValidator>
|
||||
</cc1:PropertyPanel>
|
||||
</cc1:Pane>
|
||||
<asp:Panel ID="panel_buttons" runat="server">
|
||||
<p>
|
||||
<asp:Button ID="ok" runat="server" CssClass="guiInputButton" OnClick="HandleMoveOrCopy"></asp:Button>
|
||||
<em>
|
||||
<%=umbraco.ui.Text("general", "or", this.getUser())%></em> <a href="#" style="color: blue" onclick="UmbClientMgr.closeModalWindow()">
|
||||
<%=umbraco.ui.Text("general", "cancel", this.getUser())%></a>
|
||||
</p>
|
||||
</asp:Panel>
|
||||
</asp:Content>
|
||||
@@ -1,17 +1,19 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
using System.Xml;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using umbraco.BasePages;
|
||||
using umbraco.cms.businesslogic.web;
|
||||
using umbraco.presentation;
|
||||
using umbraco.cms.businesslogic.media;
|
||||
using System.Linq;
|
||||
using umbraco.cms.businesslogic;
|
||||
using umbraco.cms.presentation.user;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Web;
|
||||
|
||||
namespace umbraco.dialogs
|
||||
{
|
||||
@@ -22,13 +24,13 @@ namespace umbraco.dialogs
|
||||
{
|
||||
|
||||
protected override void OnInit(EventArgs e)
|
||||
{
|
||||
{
|
||||
CurrentApp = Request["app"];
|
||||
|
||||
base.OnInit(e);
|
||||
}
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
JTree.DataBind();
|
||||
|
||||
@@ -48,7 +50,7 @@ namespace umbraco.dialogs
|
||||
ok.Text = ui.Text("general", "ok", this.getUser());
|
||||
ok.Attributes.Add("style", "width: 60px");
|
||||
|
||||
var documentType = new DocumentType(int.Parse(helper.Request("id")));
|
||||
var documentType = new DocumentType(int.Parse(Request.GetItemAsString("id")));
|
||||
|
||||
//Load master types...
|
||||
masterType.Attributes.Add("style", "width: 350px;");
|
||||
@@ -72,81 +74,74 @@ namespace umbraco.dialogs
|
||||
pane_settings.Visible = false;
|
||||
|
||||
// Caption and properies on BUTTON
|
||||
ok.Text = ui.Text("general", "ok", this.getUser());
|
||||
ok.Text = ui.Text("general", "ok", getUser());
|
||||
ok.Attributes.Add("style", "width: 60px");
|
||||
ok.Attributes.Add("disabled", "true");
|
||||
|
||||
var cmsNode = new CMSNode(int.Parse(helper.Request("id")));
|
||||
IContentBase currContent;
|
||||
if (CurrentApp == "content")
|
||||
{
|
||||
currContent = Services.ContentService.GetById(Request.GetItemAs<int>("id"));
|
||||
}
|
||||
else
|
||||
{
|
||||
currContent = Services.MediaService.GetById(Request.GetItemAs<int>("id"));
|
||||
}
|
||||
|
||||
var validAction = true;
|
||||
if (CurrentApp == "content" && cmsNode.HasChildren)
|
||||
validAction = ValidAction(helper.Request("mode") == "cut" ? 'M' : 'O');
|
||||
|
||||
|
||||
if (helper.Request("mode") == "cut")
|
||||
if (CurrentApp == "content" && Umbraco.Core.Models.ContentExtensions.HasChildren(currContent, Services))
|
||||
{
|
||||
pane_form.Text = ui.Text("moveOrCopy", "moveTo", cmsNode.Text, base.getUser());
|
||||
validAction = ValidAction(currContent, Request.GetItemAsString("mode") == "cut" ? 'M' : 'O');
|
||||
}
|
||||
|
||||
if (Request.GetItemAsString("mode") == "cut")
|
||||
{
|
||||
pane_form.Text = ui.Text("moveOrCopy", "moveTo", currContent.Name, getUser());
|
||||
pp_relate.Visible = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pane_form.Text = ui.Text("moveOrCopy", "copyTo", cmsNode.Text, base.getUser());
|
||||
pane_form.Text = ui.Text("moveOrCopy", "copyTo", currContent.Name, getUser());
|
||||
pp_relate.Visible = true;
|
||||
}
|
||||
|
||||
if (validAction == false)
|
||||
{
|
||||
ScriptManager.RegisterStartupScript(this, this.GetType(), "notvalid", "notValid();", true);
|
||||
ScriptManager.RegisterStartupScript(this, GetType(), "notvalid", "notValid();", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private bool ValidAction(char actionLetter)
|
||||
private bool ValidAction(IContentBase cmsNode, char actionLetter)
|
||||
{
|
||||
var cmsNode = new CMSNode(int.Parse(helper.Request("id")));
|
||||
var currentAction = BusinessLogic.Actions.Action.GetPermissionAssignable().First(a => a.Letter == actionLetter);
|
||||
return CheckPermissions(cmsNode, currentAction);
|
||||
}
|
||||
|
||||
private bool CheckPermissions(CMSNode node, IAction currentAction)
|
||||
{
|
||||
private bool CheckPermissions(IContentBase node, IAction currentAction)
|
||||
{
|
||||
var currUserPermissions = new UserPermissions(CurrentUser);
|
||||
var lstCurrUserActions = currUserPermissions.GetExistingNodePermission(node.Id);
|
||||
|
||||
if (lstCurrUserActions.Contains(currentAction) == false)
|
||||
return false;
|
||||
|
||||
if (node.HasChildren)
|
||||
|
||||
if (Umbraco.Core.Models.ContentExtensions.HasChildren(node, Services))
|
||||
{
|
||||
foreach (CMSNode child in node.Children)
|
||||
if (CheckPermissions(child, currentAction) == false)
|
||||
return false;
|
||||
return Umbraco.Core.Models.ContentExtensions.Children(node, Services)
|
||||
.All(child => CheckPermissions(child, currentAction));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//PPH moving multiple nodes and publishing them aswell.
|
||||
private void handleChildNodes(cms.businesslogic.web.Document document)
|
||||
{
|
||||
//store children array here because iterating over an Array object is very inneficient.
|
||||
var children = document.Children;
|
||||
foreach (Document child in children.Where(child => child.Published))
|
||||
{
|
||||
child.Publish(new BusinessLogic.User(0));
|
||||
|
||||
//using library.publish to support load balancing.
|
||||
library.UpdateDocumentCache(child.Id);
|
||||
if (child.HasChildren)
|
||||
handleChildNodes(child);
|
||||
}
|
||||
}
|
||||
|
||||
//PPH Handle doctype copies..
|
||||
private void HandleDocumentTypeCopy()
|
||||
{
|
||||
var documentType = new DocumentType(int.Parse(helper.Request("id")));
|
||||
var documentType = new DocumentType(int.Parse(Request.GetItemAsString("id")));
|
||||
|
||||
//Documentype exists.. create new doc type...
|
||||
var alias = rename.Text;
|
||||
@@ -200,53 +195,66 @@ namespace umbraco.dialogs
|
||||
public void HandleMoveOrCopy(object sender, EventArgs e)
|
||||
{
|
||||
if (CurrentApp == "settings")
|
||||
HandleDocumentTypeCopy();
|
||||
else
|
||||
HandleDocumentTypeCopy();
|
||||
else
|
||||
HandleDocumentMoveOrCopy();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPreRender(EventArgs e)
|
||||
{
|
||||
base.OnPreRender(e);
|
||||
ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/cmsnode.asmx"));
|
||||
ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/legacyAjaxCalls.asmx"));
|
||||
}
|
||||
base.OnPreRender(e);
|
||||
ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/cmsnode.asmx"));
|
||||
ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/legacyAjaxCalls.asmx"));
|
||||
}
|
||||
|
||||
private void HandleDocumentMoveOrCopy()
|
||||
{
|
||||
if (helper.Request("copyTo") != "" && helper.Request("id") != "")
|
||||
if (Request.GetItemAsString("copyTo") != "" && Request.GetItemAsString("id") != "")
|
||||
{
|
||||
// Check if the current node is allowed at new position
|
||||
var nodeAllowed = false;
|
||||
|
||||
var currentNode = new cms.businesslogic.Content(int.Parse(helper.Request("id")));
|
||||
|
||||
var newNode = new cms.businesslogic.Content(int.Parse(helper.Request("copyTo")));
|
||||
IContentBase currContent;
|
||||
IContentBase parentContent;
|
||||
IContentTypeBase parentContentType;
|
||||
if (CurrentApp == "content")
|
||||
{
|
||||
currContent = Services.ContentService.GetById(Request.GetItemAs<int>("id"));
|
||||
parentContent = Services.ContentService.GetById(Request.GetItemAs<int>("copyTo"));
|
||||
parentContentType = Services.ContentTypeService.GetContentType(parentContent.ContentTypeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
currContent = Services.MediaService.GetById(Request.GetItemAs<int>("id"));
|
||||
parentContent = Services.MediaService.GetById(Request.GetItemAs<int>("copyTo"));
|
||||
parentContentType = Services.ContentTypeService.GetMediaType(parentContent.ContentTypeId);
|
||||
}
|
||||
|
||||
// Check on contenttypes
|
||||
if (int.Parse(helper.Request("copyTo")) == -1)
|
||||
if (Request.GetItemAs<int>("copyTo") == -1)
|
||||
{
|
||||
nodeAllowed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newNode.ContentType.AllowedChildContentTypeIDs.Where(c => c == currentNode.ContentType.Id).Any())
|
||||
var allowedChildContentTypeIds = parentContentType.AllowedContentTypes.Select(x => x.Id).ToArray();
|
||||
if (allowedChildContentTypeIds.Any(x => x.Value == currContent.ContentTypeId))
|
||||
{
|
||||
nodeAllowed = true;
|
||||
}
|
||||
|
||||
if (nodeAllowed == false)
|
||||
{
|
||||
feedback.Text = ui.Text("moveOrCopy", "notAllowedByContentType", base.getUser());
|
||||
feedback.Text = ui.Text("moveOrCopy", "notAllowedByContentType", getUser());
|
||||
feedback.type = uicontrols.Feedback.feedbacktype.error;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check on paths
|
||||
if ((string.Format(",{0},", newNode.Path)).IndexOf(string.Format(",{0},", currentNode.Id)) > -1)
|
||||
if ((string.Format(",{0},", parentContent.Path)).IndexOf(string.Format(",{0},", currContent.Id)) > -1)
|
||||
{
|
||||
nodeAllowed = false;
|
||||
feedback.Text = ui.Text("moveOrCopy", "notAllowedByPath", base.getUser());
|
||||
feedback.Text = ui.Text("moveOrCopy", "notAllowedByPath", getUser());
|
||||
feedback.type = uicontrols.Feedback.feedbacktype.error;
|
||||
}
|
||||
}
|
||||
@@ -258,46 +266,171 @@ namespace umbraco.dialogs
|
||||
pane_form_notice.Visible = false;
|
||||
panel_buttons.Visible = false;
|
||||
|
||||
var newNodeCaption = newNode.Id == -1 ? ui.Text(CurrentApp) : newNode.Text;
|
||||
var newNodeCaption = Request.GetItemAs<int>("copyTo") == -1
|
||||
? ui.Text(CurrentApp)
|
||||
: parentContent.Name;
|
||||
|
||||
string[] nodes = { currentNode.Text, newNodeCaption };
|
||||
string[] nodes = { currContent.Name, newNodeCaption };
|
||||
|
||||
if (Request["mode"] == "cut")
|
||||
{
|
||||
if (CurrentApp == "content")
|
||||
{
|
||||
//PPH changed this to document instead of cmsNode to handle republishing.
|
||||
var documentId = int.Parse(helper.Request("id"));
|
||||
var document = new Document(documentId);
|
||||
document.Move(int.Parse(helper.Request("copyTo")));
|
||||
library.RefreshContent();
|
||||
Services.ContentService.Move((IContent)currContent, Request.GetItemAs<int>("copyTo"), getUser().Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
var media = new Media(int.Parse(UmbracoContext.Current.Request["id"]));
|
||||
media.Move(int.Parse(UmbracoContext.Current.Request["copyTo"]));
|
||||
media = new Media(int.Parse(UmbracoContext.Current.Request["id"]));
|
||||
media.XmlGenerate(new XmlDocument());
|
||||
library.ClearLibraryCacheForMedia(media.Id);
|
||||
Services.MediaService.Move((IMedia)currContent, Request.GetItemAs<int>("copyTo"), getUser().Id);
|
||||
library.ClearLibraryCacheForMedia(currContent.Id);
|
||||
}
|
||||
|
||||
feedback.Text = ui.Text("moveOrCopy", "moveDone", nodes, getUser()) + "</p><p><a href='#' onclick='" + ClientTools.Scripts.CloseModalWindow() + "'>" + ui.Text("closeThisWindow") + "</a>";
|
||||
feedback.type = uicontrols.Feedback.feedbacktype.success;
|
||||
|
||||
// refresh tree
|
||||
ClientTools.MoveNode(currentNode.Id.ToString(), newNode.Path);
|
||||
ClientTools.MoveNode(currContent.Id.ToString(), parentContent.Path);
|
||||
}
|
||||
else
|
||||
{
|
||||
var document = new Document(int.Parse(helper.Request("id")));
|
||||
document.Copy(int.Parse(helper.Request("copyTo")), this.getUser(), RelateDocuments.Checked);
|
||||
feedback.Text = ui.Text("moveOrCopy", "copyDone", nodes, base.getUser()) + "</p><p><a href='#' onclick='" + ClientTools.Scripts.CloseModalWindow() + "'>" + ui.Text("closeThisWindow") + "</a>";
|
||||
//NOTE: We ONLY support Copy on content not media for some reason.
|
||||
|
||||
Services.ContentService.Copy((IContent)currContent, Request.GetItemAs<int>("copyTo"), RelateDocuments.Checked, getUser().Id);
|
||||
|
||||
feedback.Text = ui.Text("moveOrCopy", "copyDone", nodes, getUser()) + "</p><p><a href='#' onclick='" + ClientTools.Scripts.CloseModalWindow() + "'>" + ui.Text("closeThisWindow") + "</a>";
|
||||
feedback.type = uicontrols.Feedback.feedbacktype.success;
|
||||
ClientTools.CopyNode(currentNode.Id.ToString(), newNode.Path);
|
||||
|
||||
// refresh tree
|
||||
ClientTools.CopyNode(currContent.Id.ToString(), parentContent.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// JsInclude1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::ClientDependency.Core.Controls.JsInclude JsInclude1;
|
||||
|
||||
/// <summary>
|
||||
/// feedback control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.Feedback feedback;
|
||||
|
||||
/// <summary>
|
||||
/// pane_form control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.Pane pane_form;
|
||||
|
||||
/// <summary>
|
||||
/// JTree control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.controls.Tree.TreeControl JTree;
|
||||
|
||||
/// <summary>
|
||||
/// pp_relate control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.PropertyPanel pp_relate;
|
||||
|
||||
/// <summary>
|
||||
/// RelateDocuments control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.CheckBox RelateDocuments;
|
||||
|
||||
/// <summary>
|
||||
/// pane_form_notice control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.PlaceHolder pane_form_notice;
|
||||
|
||||
/// <summary>
|
||||
/// pane_settings control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.Pane pane_settings;
|
||||
|
||||
/// <summary>
|
||||
/// PropertyPanel1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.PropertyPanel PropertyPanel1;
|
||||
|
||||
/// <summary>
|
||||
/// masterType control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.ListBox masterType;
|
||||
|
||||
/// <summary>
|
||||
/// rename control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.TextBox rename;
|
||||
|
||||
/// <summary>
|
||||
/// RequiredFieldValidator1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator1;
|
||||
|
||||
/// <summary>
|
||||
/// panel_buttons control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Panel panel_buttons;
|
||||
|
||||
/// <summary>
|
||||
/// ok control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Button ok;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace umbraco.dialogs {
|
||||
|
||||
|
||||
public partial class moveOrCopy {
|
||||
|
||||
/// <summary>
|
||||
/// JsInclude1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::ClientDependency.Core.Controls.JsInclude JsInclude1;
|
||||
|
||||
/// <summary>
|
||||
/// feedback control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.Feedback feedback;
|
||||
|
||||
/// <summary>
|
||||
/// pane_form control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.Pane pane_form;
|
||||
|
||||
/// <summary>
|
||||
/// JTree control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.controls.Tree.TreeControl JTree;
|
||||
|
||||
/// <summary>
|
||||
/// pp_relate control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.PropertyPanel pp_relate;
|
||||
|
||||
/// <summary>
|
||||
/// RelateDocuments control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.CheckBox RelateDocuments;
|
||||
|
||||
/// <summary>
|
||||
/// pane_form_notice control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.PlaceHolder pane_form_notice;
|
||||
|
||||
/// <summary>
|
||||
/// pane_settings control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.Pane pane_settings;
|
||||
|
||||
/// <summary>
|
||||
/// PropertyPanel1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::umbraco.uicontrols.PropertyPanel PropertyPanel1;
|
||||
|
||||
/// <summary>
|
||||
/// masterType control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.ListBox masterType;
|
||||
|
||||
/// <summary>
|
||||
/// rename control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.TextBox rename;
|
||||
|
||||
/// <summary>
|
||||
/// RequiredFieldValidator1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator1;
|
||||
|
||||
/// <summary>
|
||||
/// panel_buttons control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Panel panel_buttons;
|
||||
|
||||
/// <summary>
|
||||
/// ok control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Button ok;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using System.Web.Routing;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Services;
|
||||
using umbraco.BusinessLogic;
|
||||
using umbraco.DataLayer;
|
||||
using Umbraco.Core;
|
||||
@@ -53,6 +54,30 @@ namespace umbraco.BasePages
|
||||
get { return umbraco.BusinessLogic.Application.SqlHelper; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current ApplicationContext
|
||||
/// </summary>
|
||||
public ApplicationContext ApplicationContext
|
||||
{
|
||||
get { return ApplicationContext.Current; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a ServiceContext
|
||||
/// </summary>
|
||||
public ServiceContext Services
|
||||
{
|
||||
get { return ApplicationContext.Services; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a DatabaseContext
|
||||
/// </summary>
|
||||
public DatabaseContext DatabaseContext
|
||||
{
|
||||
get { return ApplicationContext.DatabaseContext; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BasePage"/> class.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user