using System; using System.Text; using System.Web; using System.Web.UI; using CMS.CMSHelper; using CMS.DocumentEngine; using CMS.EventLog; using CMS.ExtendedControls; using CMS.GlobalHelper; using CMS.SettingsProvider; using CMS.UIControls; public partial class CMSModules_Content_Controls_CMSDeskTree : CMSUserControl, IPostBackEventHandler { #region "Properties" /// /// Requested action. /// protected string Action { get { return ValidationHelper.GetString(Request.Form["hdnAction"], string.Empty); } } /// /// Action parameter 1. /// protected string Param1 { get { return ValidationHelper.GetString(Request.Form["hdnParam1"], string.Empty); } } /// /// Action parameter 2. /// protected string Param2 { get { return ValidationHelper.GetString(Request.Form["hdnParam2"], string.Empty); } } /// /// Scrollbar position. /// protected int ScrollPosition { get { return ValidationHelper.GetInteger(Request.Form["hdnScroll"], 0); } } /// /// Node to be expanded. /// private int NodeID { get { return ValidationHelper.GetInteger(GetValue("NodeID"), 0); } set { SetValue("NodeID", value); } } /// /// Culture of the tree. /// private string Culture { get { return ValidationHelper.GetString(GetValue("Culture"), string.Empty); } set { SetValue("Culture", value); } } /// /// Node to be expanded. /// private int ExpandNodeID { get { return ValidationHelper.GetInteger(GetValue("ExpandNodeID"), 0); } set { SetValue("ExpandNodeID", value); } } /// /// Determines whether the tree is used for browsing products. /// public bool IsProductTree { get { return ValidationHelper.GetBoolean(GetValue("IsProductTree"), false); } set { SetValue("IsProductTree", value); } } /// /// Indicates global objects are allowed on current site besides site-specific ones. Type of the objects depends on settings key name /// set in GlobalObjectsKeyName property. /// public bool AllowGlobalObjects { get { return ValidationHelper.GetBoolean(GetValue("AllowGlobalObjects"), false); } set { SetValue("AllowGlobalObjects", value); } } /// /// Indicates if products will be displayed in products sections tree. This setting has no effect when not using sections tree. /// public bool DisplayProductsInSectionsTree { get { return ValidationHelper.GetBoolean(GetValue("DisplayProductsInSectionsTree"), false); } set { SetValue("DisplayProductsInSectionsTree", value); } } /// /// Indicates whether it is possible to create products without document data. /// public bool AllowProductsWithoutDocuments { get { return ValidationHelper.GetBoolean(GetValue("AllowProductsWithoutDocuments"), false); } set { SetValue("AllowProductsWithoutDocuments", value); } } /// /// Determines from which node should tree display nodes. /// public string StartingAliasPath { get { return ValidationHelper.GetString(GetValue("StartingAliasPath"), CMSContext.CurrentUser.UserStartingAliasPath); } set { SetValue("StartingAliasPath", value); } } /// /// Javascript called before selecting a node. /// public string BeforeSelectNodeScript { get { return ValidationHelper.GetString(GetValue("BeforeSelectNodeScript"), ""); } set { SetValue("BeforeSelectNodeScript", value); } } #endregion #region "Page events" protected override void OnInit(EventArgs e) { if (!Page.IsCallback && RequestHelper.IsPostBack()) { NodeID = ValidationHelper.GetInteger(Param1, 0); if (Action.ToLowerCSafe() == "refresh") { ExpandNodeID = ValidationHelper.GetInteger(Param2, 0); } } // Set up the tree if ((NodeID > 0) && !RequestHelper.IsPostBack()) { treeElem.SelectedNodeID = NodeID; // Setup the current node script AddScript(string.Format("currentNodeId = {0};", NodeID)); } treeElem.ExpandNodeID = ExpandNodeID; treeElem.Culture = Culture; treeElem.NodeTextTemplate = string.Format("{0}##ICON####NODENAME##{1}", ContextMenuContainer.GetStartTag("nodeMenu", "##NODEID##", false, false), ContextMenuContainer.GetEndTag(false), BeforeSelectNodeScript); treeElem.SelectedNodeTextTemplate = string.Format("{0}##ICON####NODENAME##{1}", ContextMenuContainer.GetStartTag("nodeMenu", "##NODEID##", false, false), ContextMenuContainer.GetEndTag(false), BeforeSelectNodeScript); treeElem.MaxTreeNodeText = string.Format("{0}", GetString("ContentTree.SeeListing")); treeElem.SelectPublishedData = false; if (IsProductTree) { menuCont.MenuControlPath = "~/CMSModules/Ecommerce/Controls/UI/ProductSectionsContextMenu.ascx"; treeElem.RootNodeCreated += treeElem_RootNodeCreated; // Filter only product section nodes string where = "NodeClassID IN (SELECT ClassID FROM CMS_Class WHERE ClassIsProductSection = 1)"; // Check if products are to be displayed in tree if (DisplayProductsInSectionsTree) { // Include product documents where = SqlHelperClass.AddWhereCondition(where, "(NodeSKUID IS NOT NULL)", "OR"); } treeElem.MapProvider.WhereCondition = SqlHelperClass.AddWhereCondition(treeElem.MapProvider.WhereCondition, where); } else { menuCont.MenuControlPath = "~/CMSModules/Content/Controls/TreeContextMenu.ascx"; } if (!string.IsNullOrEmpty(StartingAliasPath)) { treeElem.Path = StartingAliasPath; } base.OnInit(e); } protected void Page_Load(object sender, EventArgs e) { if (!Page.IsCallback) { // Register the dialog script ScriptHelper.RegisterJQuery(Page); ScriptHelper.RegisterDialogScript(Page); string script = @" function InitTreeParams(action, param1, param2) { var elm = jQuery('#" + pnlTreeArea.ClientID + @"'); jQuery('#hdnScroll').val(elm.scrollTop()); jQuery('#hdnAction').val(action); jQuery('#hdnParam1').val(param1); jQuery('#hdnParam2').val(param2); } function ProcessRequest(action, param1, param2) { InitTreeParams(action, param1, param2); " + Page.ClientScript.GetPostBackEventReference(this, null) + ";" + @"} "; iconRefresh.OnClientClick = "TreeRefresh();"; ScriptHelper.RegisterClientScriptBlock(this, typeof(string), "processRequestScript", ScriptHelper.GetScript(script)); AddScript("var currentNode = document.getElementById('treeSelectedNode');"); } } protected override void Render(HtmlTextWriter writer) { // Render control as a div with ID (to ensure IPostBackEventHandler works in UpdatePanel) writer.WriteBeginTag("div"); writer.WriteAttribute("id", ClientID); writer.Write(HtmlTextWriter.TagRightChar); base.Render(writer); writer.WriteEndTag("div"); } #endregion #region "IPostBackEventHandler members" public void RaisePostBackEvent(string eventArgument) { CurrentUserInfo currentUser = CMSContext.CurrentUser; // Current Node ID int nodeId = ValidationHelper.GetInteger(Param1, 0); TreeProvider tree = new TreeProvider(currentUser); EventLogProvider log = new EventLogProvider(); string documentName = string.Empty; string action = Action.ToLowerCSafe(); string siteName = CMSContext.CurrentSiteName; // Process the request switch (action) { case "refresh": treeElem.SelectedNodeID = nodeId; AddScript("currentNodeId = " + nodeId + ";"); break; case "moveup": case "movedown": case "movetop": case "movebottom": // Move the document up (document order) try { if (nodeId == 0) { AddAlert(GetString("ContentRequest.ErrorMissingSource")); return; } // Get document to move TreeNode node = tree.SelectSingleNode(nodeId); // Check the permissions for document if (currentUser.IsAuthorizedPerDocument(node, NodePermissionsEnum.Modify) == AuthorizationResultEnum.Allowed) { // Root of products tree can not be moved if (!IsProductTree || (node.NodeAliasPath.CompareToCSafe(StartingAliasPath, true) != 0)) { switch (action) { case "moveup": node = tree.MoveNodeUp(nodeId); break; case "movedown": node = tree.MoveNodeDown(nodeId); break; case "movetop": node = tree.SelectSingleNode(nodeId); tree.SetNodeOrder(nodeId, DocumentOrderEnum.First); break; case "movebottom": node = tree.SelectSingleNode(nodeId); tree.SetNodeOrder(nodeId, DocumentOrderEnum.Last); break; } if (node != null) { // Log the synchronization tasks for the entire tree level DocumentSynchronizationHelper.LogDocumentChangeOrder(siteName, node.NodeAliasPath, tree); // Select the document in the tree documentName = node.GetDocumentName(); treeElem.ExpandNodeID = node.NodeParentID; treeElem.SelectedNodeID = node.NodeID; AddScript("currentNodeId = " + node.NodeID + ";"); } else { AddAlert(GetString("ContentRequest.MoveFailed")); } } } else { // Select the document in the tree treeElem.SelectedNodeID = nodeId; AddAlert(GetString("ContentRequest.MoveDenied")); } } catch (Exception ex) { log.LogEvent(EventLogProvider.EVENT_TYPE_ERROR, DateTime.Now, "Content", "MOVE", currentUser.UserID, currentUser.UserName, nodeId, documentName, HTTPHelper.UserHostAddress, EventLogProvider.GetExceptionLogMessage(ex), CMSContext.CurrentSite.SiteID, HTTPHelper.GetAbsoluteUri()); AddAlert(GetString("ContentRequest.MoveFailed") + " : " + ex.Message); } break; case "setculture": // Set the preferred culture code try { // Set the culture code string language = ValidationHelper.GetString(Param2, string.Empty); if (!string.IsNullOrEmpty(language)) { CMSContext.PreferredCultureCode = language; treeElem.Culture = language; } // Refresh the document if (nodeId > 0) { treeElem.SelectedNodeID = nodeId; AddScript("SelectNode(" + nodeId + ");"); } } catch (Exception ex) { log.LogEvent(EventLogProvider.EVENT_TYPE_ERROR, DateTime.Now, "Content", "SETCULTURE", currentUser.UserID, currentUser.UserName, nodeId, documentName, HTTPHelper.UserHostAddress, EventLogProvider.GetExceptionLogMessage(ex), CMSContext.CurrentSite.SiteID, HTTPHelper.GetAbsoluteUri()); AddAlert(GetString("ContentRequest.ErrorChangeLanguage")); } break; case "setdevice": // Set the device profile try { // Set the device name string deviceName = ValidationHelper.GetString(Param2, string.Empty); CMSContext.CurrentDeviceProfileName = deviceName; // Refresh the document if (nodeId > 0) { treeElem.SelectedNodeID = nodeId; AddScript("SelectNode(" + nodeId + ");"); } } catch (Exception ex) { log.LogEvent(EventLogProvider.EVENT_TYPE_ERROR, DateTime.Now, "Content", "SETDEVICE", currentUser.UserID, currentUser.UserName, nodeId, documentName, HTTPHelper.UserHostAddress, EventLogProvider.GetExceptionLogMessage(ex), CMSContext.CurrentSite.SiteID, HTTPHelper.GetAbsoluteUri()); AddAlert(GetString("ContentRequest.ErrorChangeLanguage")); } break; // Sorting case "sortalphaasc": case "sortalphadesc": case "sortdateasc": case "sortdatedesc": // Set the preferred culture code try { // Get document to sort TreeNode node = tree.SelectSingleNode(nodeId); // Check the permissions for document if ((currentUser.IsAuthorizedPerDocument(node, NodePermissionsEnum.Modify) == AuthorizationResultEnum.Allowed) && (currentUser.IsAuthorizedPerDocument(node, NodePermissionsEnum.ExploreTree) == AuthorizationResultEnum.Allowed)) { switch (action) { case "sortalphaasc": tree.OrderNodesAlphabetically(nodeId, true); break; case "sortalphadesc": tree.OrderNodesAlphabetically(nodeId, false); break; case "sortdateasc": tree.OrderNodesByDate(nodeId, true); break; case "sortdatedesc": tree.OrderNodesByDate(nodeId, false); break; } // Log the synchronization tasks for the entire tree level string fakeAlias = node.NodeAliasPath.TrimEnd('/') + "/child"; DocumentSynchronizationHelper.LogDocumentChangeOrder(siteName, fakeAlias, tree); } else { AddAlert(GetString("ContentRequest.SortDenied")); } // Refresh the tree if (nodeId > 0) { treeElem.ExpandNodeID = nodeId; treeElem.SelectedNodeID = nodeId; if (IsProductTree) { AddScript("window.frames['contentview'].location.replace(window.frames['contentview'].location);"); } else { AddScript("SelectNode(" + nodeId + ");"); } } } catch (Exception ex) { log.LogEvent(EventLogProvider.EVENT_TYPE_ERROR, DateTime.Now, "Content", "SORT", currentUser.UserID, currentUser.UserName, nodeId, documentName, HTTPHelper.UserHostAddress, EventLogProvider.GetExceptionLogMessage(ex), CMSContext.CurrentSite.SiteID, HTTPHelper.GetAbsoluteUri()); AddAlert(GetString("ContentRequest.ErrorSort")); } break; } // Maintain scrollbar position string script = @" SetSelectedNodeId(currentNodeId); MaintainScroll('" + nodeId + @"','" + pnlTreeArea.ClientID + @"', " + ScrollPosition + @"); HideAllContextMenus(); "; ScriptHelper.RegisterStartupScript(Page, typeof(string), "MaintainScrollbar", script, true); } #endregion #region "Methods" /// /// Adds the alert message to the output request window. /// /// Message to display private void AddAlert(string message) { ScriptHelper.RegisterStartupScript(this, typeof(string), message.GetHashCode().ToString(), ScriptHelper.GetAlertScript(message)); } /// /// Adds the script to the output request window. /// /// Script to add public void AddScript(string script) { ScriptHelper.RegisterStartupScript(this, typeof(string), script.GetHashCode().ToString(), ScriptHelper.GetScript(script)); } protected void treeElem_RootNodeCreated(object sender, EventArgs e) { // Add "Unassigned products" node when global products or products without document allowed if (AllowGlobalObjects || AllowProductsWithoutDocuments) { UITreeView treeControl = sender as UITreeView; if (treeControl != null) { System.Web.UI.WebControls.TreeNode newNode = new System.Web.UI.WebControls.TreeNode(); string imageUrl = GetImageUrl("Objects/Ecommerce_SKU/list.png"); string tooltip = GetString("com.productstree.unassignedtooltip"); // Set the base data newNode.Value = "-1"; newNode.NavigateUrl = "javascript:void(0);"; // Prepare icon StringBuilder sb = new StringBuilder(); sb.Append("\"\""); string imageTag = sb.ToString(); // Prepare name string nodeName = HttpUtility.HtmlEncode(GetString("com.productstree.unassigned")); string nodeNameJava = ScriptHelper.GetString(nodeName); newNode.Text = treeElem.NodeTextTemplate.Replace("##NODEID##", "-1").Replace("##NODENAMEJAVA##", nodeNameJava).Replace("##NODENAME##", nodeName).Replace("##ICON##", imageTag); const int childNodesCount = 0; newNode.Text = newNode.Text.Replace("##NODECHILDNODESCOUNT##", childNodesCount.ToString()); // Insert node to the top of tree treeControl.Nodes.AddAt(0, newNode); } } } #endregion }