{"id":3047,"date":"2023-12-07T21:11:55","date_gmt":"2023-12-08T02:11:55","guid":{"rendered":"https:\/\/xlinesoft.com\/blog\/?p=3047"},"modified":"2023-12-08T10:56:46","modified_gmt":"2023-12-08T15:56:46","slug":"drag-and-drop-between-dashboard-elements","status":"publish","type":"post","link":"https:\/\/xlinesoft.com\/blog\/2023\/12\/07\/drag-and-drop-between-dashboard-elements\/","title":{"rendered":"Drag-and-drop between dashboard elements"},"content":{"rendered":"<p>In this article we will show how you can implement drag-n-drop between two dashboard elements. It makes more sense to drag and drop records between two grids. In this example we will be using two tables named <strong>orders<\/strong> and <strong>orders_archive<\/strong>.<\/p>\n<p>This is how it is going to look in the generated application:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/xlinesoft.com\/blog\/wp-content\/uploads\/2023\/12\/drag-n-drop.gif\" alt=\"\" width=\"1357\" height=\"832\" class=\"alignnone size-full wp-image-3050\" \/><br \/>\n<!--more--><\/p>\n<p>1. SQL query that creates required tables in the database<\/p>\n<div class=\"my-syntax-highlighter\">\n<pre><textarea id=\"mshighlighter\" class=\"mshighlighter\" language=\"sql\" name=\"mshighlighter\" >\r\nCREATE TABLE `orders`(`OrderID` int NOT NULL AUTO_INCREMENT, `CustomerID` varchar(5) NULL DEFAULT NULL, `EmployeeID` int NULL DEFAULT NULL, `OrderDate` datetime NULL DEFAULT NULL, `RequiredDate` datetime NULL DEFAULT NULL, `ShippedDate` datetime NULL DEFAULT NULL, `ShipVia` int NULL DEFAULT NULL, `Freight` decimal(12,2) NULL DEFAULT 0.00, `ShipName` varchar(40) NULL DEFAULT NULL, `ShipAddress` varchar(60) NULL DEFAULT NULL, `ShipCity` varchar(15) NULL DEFAULT NULL, `ShipRegion` varchar(15) NULL DEFAULT NULL, `ShipPostalCode` varchar(10) NULL DEFAULT NULL, `ShipCountry` varchar(15) NULL DEFAULT NULL, `Complited` tinyint NOT NULL DEFAULT 0, `order` int NULL DEFAULT NULL, PRIMARY KEY (`OrderID`))CHARACTER SET utf8;\r\nCREATE TABLE `orders_archive`(`OrderID` int NOT NULL AUTO_INCREMENT, `CustomerID` varchar(5) NULL DEFAULT NULL, `EmployeeID` int NULL DEFAULT NULL, `OrderDate` datetime NULL DEFAULT NULL, `RequiredDate` datetime NULL DEFAULT NULL, `ShippedDate` datetime NULL DEFAULT NULL, `ShipVia` int NULL DEFAULT NULL, `Freight` decimal(12,2) NULL DEFAULT 0.00, `ShipName` varchar(40) NULL DEFAULT NULL, `ShipAddress` varchar(60) NULL DEFAULT NULL, `ShipCity` varchar(15) NULL DEFAULT NULL, `ShipRegion` varchar(15) NULL DEFAULT NULL, `ShipPostalCode` varchar(10) NULL DEFAULT NULL, `ShipCountry` varchar(15) NULL DEFAULT NULL, `Complited` tinyint NOT NULL DEFAULT 0, `order` int NULL DEFAULT NULL, PRIMARY KEY (`OrderID`))CHARACTER SET utf8;<\/textarea><\/pre>\n<\/div>\n<p>2. Create a dashboard in PHPRunner or ASPRunner.NET and add those two tables there.<\/p>\n<p>3. The following code goes to Javascript OnLoad event of both <strong>orders<\/strong> and <strong>orders_archive<\/strong> table List Pages.<\/p>\n<p>Things to change:<br \/>\n&#8211; var connectTable should contain the name of another table. In <strong>orders<\/strong> table code it should say &#8220;orders_archive&#8221; and vice versa.<br \/>\n&#8211; &#8220;dashboard_dashboard.php&#8221; URL of the dashboard page. In ASPRunner.NET it will be something like <strong>dashboard<\/strong><br \/>\n&#8211; &#8220;OrderID&#8221; &#8211; name of the key column of the current table.<\/p>\n<div class=\"my-syntax-highlighter\">\n<pre><textarea id=\"mshighlighter\" class=\"mshighlighter\" language=\"javascript\" name=\"mshighlighter\" >\r\n$(\"[data-grid-message]\").hide();\r\n$(\"[data-location='grid']\").show();\r\n\r\nvar connectTable = \"orders_archive\";\r\n\r\nif(pageObj.dashboard){\r\n     \/\/ to initialize a plugin we will use a container where there grid is placed on the dashboard\r\n    var panel = $( \" > tbody\",pageObj.gridElem ).parents(\".panel-body\");\r\n    panel.sortable({\r\n      connectWith: \"#dashelement_\"+connectTable+\"_grid\"+pageObj.dashboard.id+\" .panel-body\",\r\n      items: 'tbody .r-gridrow',\r\n      helper: 'clone',\r\n      opacity: 0.6,\r\n      stop:function(e,ui){\r\n         if ($(e.target).has(ui.item).length) \r\n          $(e.target).sortable(\"cancel\");\r\n      },\r\n      receive: function( e, ui ) {\r\n          \/\/ we moved a row from another grid\r\n        var OrderID = ui.item.find(\"[data-fieldname='OrderID']\").find(\"span\").html(),order = [];\r\n          \/\/ make a post with from and to table names and also with the OrderID that needs to be updated\r\n        $.post(\"dashboard_dashboard.php\",{a:\"replaceRow\",from:connectTable,\r\n           to:pageObj.tName,OrderID:OrderID},function(response){\r\n\t\t\t\tconsole.log(response);\r\n\t\t  });\r\n\r\n        \/\/ Update sort order as well. Not necessary but it looks better this way\r\n\r\n        $.each($(\" > tbody\",pageObj.gridElem).find(\".r-gridrow\"),function(i,row){\r\n          var orderId = $(row).find(\"[data-fieldname='OrderID']\").find(\"span\").html();\r\n          order.push({OrderID:orderId,order:(i+1)});\r\n        });\r\n        $.post(\"dashboard_dashboard.php\",{order:order,table:pageObj.tName});\r\n        \/* update 'Displaying n - n of n' for both tables *\/\r\n        \/* decrease count *\/\r\n        updateDetails( $(\"#dashelement_\"+connectTable+\"_grid\"+\r\n             pageObj.dashboard.id+\" [data-itemid='details_found']\") ,-1);\r\n        \/* increase count *\/\r\n        updateDetails( $(\"#dashelement_\"+pageObj.tName+\"_grid\"+\r\n           pageObj.dashboard.id+\" [data-itemid='details_found']\") ,1);\r\n      \r\n      }\r\n    });\r\n    function updateDetails(details,number){\r\n      var html_details = details.html(),\r\n      result_details = \/Displaying (\\d+) - (\\d+) of (\\d+)\/g.exec(html_details),\r\n      dispay = result_details[2],of = result_details[3];\r\n      html_details = html_details.replace(\/- (\\d+)\/g,\"- \"+(parseInt(dispay) + number));\r\n      html_details = html_details.replace(\/of (\\d+)\/g,\"of \"+(parseInt(of) + number));\r\n      details.html(html_details);\r\n\r\n    }\r\n};<\/textarea><\/pre>\n<\/div>\n<p>4. Dashboard page: BeforeProcess event <\/p>\n<p>In this event we add a new record to the target table and delete the same in the source table. The second section of this code helps us to update the sort order so <\/p>\n<p><strong>PHP code<\/strong><\/p>\n<div class=\"my-syntax-highlighter\">\n<pre><textarea id=\"mshighlighter\" class=\"mshighlighter\" language=\"php\" name=\"mshighlighter\" >\r\nif( postvalue(\"a\") === \"replaceRow\"){\r\n\t$fromRs = DB::Select(postvalue(\"from\"),array(\"OrderID\" => postvalue(\"OrderID\")));\r\n\t$selectError = DB::lastError();\r\n\t$fromRow = $fromRs->fetchAssoc();\r\n\tif($fromRow){\r\n\t\tDB::Insert(postvalue(\"to\"),$fromRow);\r\n\t\tDB::Delete(postvalue(\"from\"),array(\"OrderID\" => postvalue(\"OrderID\")));\r\n\t}\r\n\texit();\r\n}\r\n\r\n\/\/ update sort order if required\r\n\r\nif( postvalue(\"order\") ){\r\n$order = postvalue(\"order\") ;\r\nforeach($order as $orderInfo){\r\nDB::Update(postvalue(\"table\"),array(\"order\" => $orderInfo[\"order\"]),\r\n    array(\"OrderID\" => $orderInfo[\"OrderID\"]));\r\n}\r\nexit();\r\n}<\/textarea><\/pre>\n<\/div>\n<p><strong>C# code<\/strong><\/p>\n<div class=\"my-syntax-highlighter\">\n<pre><textarea id=\"mshighlighter\" class=\"mshighlighter\" language=\"\" name=\"mshighlighter\" >\r\nif(XVar.Equals(XVar.Pack(MVCFunctions.postvalue(new XVar(\"a\"))), XVar.Pack(\"replaceRow\")))\r\n\t\t\t{\r\n\t\t\t\tdynamic fromRow = null, fromRs = null, selectError = null;\r\n\t\t\t\tfromRs = XVar.Clone(DB.Select((XVar)(MVCFunctions.postvalue(new XVar(\"from\"))), (XVar)(new XVar(\"OrderID\", MVCFunctions.postvalue(new XVar(\"OrderID\"))))));\r\n\t\t\t\tselectError = XVar.Clone(DB.lastError());\r\n\t\t\t\tfromRow = XVar.Clone(fromRs.fetchAssoc());\r\n\t\t\t\tif(XVar.Pack(fromRow))\r\n\t\t\t\t{\r\n\t\t\t\t\tDB.Insert((XVar)(MVCFunctions.postvalue(new XVar(\"to\"))), (XVar)(fromRow));\r\n\t\t\t\t\tDB.Delete((XVar)(MVCFunctions.postvalue(new XVar(\"from\"))), (XVar)(new XVar(\"OrderID\", MVCFunctions.postvalue(new XVar(\"OrderID\")))));\r\n\t\t\t\t}\r\n\t\t\t\tMVCFunctions.ob_flush();\r\n\t\t\t\tHttpContext.Current.Response.End();\r\n\t\t\t\tthrow new RunnerInlineOutputException();\r\n\t\t\t}\r\n\t\t\tif(XVar.Pack(MVCFunctions.postvalue(new XVar(\"order\"))))\r\n\t\t\t{\r\n\t\t\t\tdynamic order = XVar.Array();\r\n\t\t\t\torder = XVar.Clone(MVCFunctions.postvalue(new XVar(\"order\")));\r\n\t\t\t\tforeach (KeyValuePair<XVar, dynamic> orderInfo in order.GetEnumerator())\r\n\t\t\t\t{\r\n\t\t\t\t\tDB.Update((XVar)(MVCFunctions.postvalue(new XVar(\"table\"))), (XVar)(new XVar(\"order\", orderInfo.Value[\"order\"])), (XVar)(new XVar(\"OrderID\", orderInfo.Value[\"OrderID\"])));\r\n\t\t\t\t}\r\n\t\t\t\tMVCFunctions.ob_flush();\r\n\t\t\t\tHttpContext.Current.Response.End();\r\n\t\t\t\tthrow new RunnerInlineOutputException();\r\n\t\t\t}\r\n\t\t\treturn null;<\/textarea><\/pre>\n<\/div>\n<p>Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article we will show how you can implement drag-n-drop between two dashboard elements. It makes more sense to drag and drop records between two grids. In this example we will be using two tables named orders and orders_archive. This is how it is going to look in the generated application:<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16,1,8],"tags":[],"class_list":["post-3047","post","type-post","status-publish","format-standard","hentry","category-asp-net","category-php-category","category-tutorials"],"_links":{"self":[{"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/posts\/3047","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/comments?post=3047"}],"version-history":[{"count":11,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/posts\/3047\/revisions"}],"predecessor-version":[{"id":3059,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/posts\/3047\/revisions\/3059"}],"wp:attachment":[{"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/media?parent=3047"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/categories?post=3047"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/xlinesoft.com\/blog\/wp-json\/wp\/v2\/tags?post=3047"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}