diff --git a/Scrummer/Code/Entities/OperationStatus.cs b/Scrummer/Code/Entities/OperationStatus.cs index 30fbcb3..b60b5b4 100644 --- a/Scrummer/Code/Entities/OperationStatus.cs +++ b/Scrummer/Code/Entities/OperationStatus.cs @@ -9,5 +9,6 @@ namespace Scrummer.Code.Entities { public bool IsOK { get; set; } public string Message { get; set; } + public string ReturnValue { get; set; } } } \ No newline at end of file diff --git a/Scrummer/Controls/CardBoardControl.cs b/Scrummer/Controls/CardBoardControl.cs index 6c757a1..d367589 100644 --- a/Scrummer/Controls/CardBoardControl.cs +++ b/Scrummer/Controls/CardBoardControl.cs @@ -83,6 +83,8 @@ namespace Scrummer.Controls sbCfg.AppendFormat(" ServiceUrl: \"{0}\",\n", _serviceUrl); sbCfg.AppendFormat(" TimePoolData: {0},\n", _timePoolData); sbCfg.AppendFormat(" Texts: {{\n"); + sbCfg.AppendFormat(" Toolbox: \"Toolbox\",\n"); + sbCfg.AppendFormat(" AddCard: \"+ Add card\",\n"); sbCfg.AppendFormat(" Accept: \"Accept\",\n"); sbCfg.AppendFormat(" Cancel: \"Cancel\",\n"); sbCfg.AppendFormat(" ConfirmDelete: \"Are you sure to delete?\",\n"); diff --git a/Scrummer/Controls/CardBoardHandler.cs b/Scrummer/Controls/CardBoardHandler.cs index 08ac572..6b8b711 100644 --- a/Scrummer/Controls/CardBoardHandler.cs +++ b/Scrummer/Controls/CardBoardHandler.cs @@ -139,7 +139,7 @@ namespace Scrummer.Controls string strIDBoard = GetRequestParm(context, "IDBoard"); int idBoard = Convert.ToInt32(string.IsNullOrEmpty(strIDBoard) ? "0" : strIDBoard); string command = GetRequestParm(context, "Command"); - + int idCard = 0; bool done = false; CardBoard cardBoard = GetCardBoard(idBoard); lock (cardBoard) @@ -150,12 +150,12 @@ namespace Scrummer.Controls string body = GetRequestParm(context, "Body"); int x = Convert.ToInt32(GetRequestParm(context, "X")); int y = Convert.ToInt32(GetRequestParm(context, "Y")); - cardBoard.Card_Create(title, body, x, y); + idCard = cardBoard.Card_Create(title, body, x, y); done = true; } if (command == "Move") { - int idCard = Convert.ToInt32(GetRequestParm(context, "IDCard")); + idCard = Convert.ToInt32(GetRequestParm(context, "IDCard")); int x = Convert.ToInt32(GetRequestParm(context, "X")); int y = Convert.ToInt32(GetRequestParm(context, "Y")); cardBoard.Card_Move(idCard, x, y); @@ -163,7 +163,7 @@ namespace Scrummer.Controls } if (command == "Edit") { - int idCard = Convert.ToInt32(GetRequestParm(context, "IDCard")); + idCard = Convert.ToInt32(GetRequestParm(context, "IDCard")); string title = GetRequestParm(context, "Title"); string body = GetRequestParm(context, "Body"); cardBoard.Card_Edit(idCard, title, body); @@ -171,7 +171,7 @@ namespace Scrummer.Controls } if (command == "Delete") { - int idCard = Convert.ToInt32(GetRequestParm(context, "IDCard")); + idCard = Convert.ToInt32(GetRequestParm(context, "IDCard")); cardBoard.Card_Delete(idCard); done = true; } @@ -179,7 +179,12 @@ namespace Scrummer.Controls if (done) { NotifyAll(); - ResponseObject(context, new OperationStatus { IsOK = true, Message = "Update successfully" }); + ResponseObject(context, new OperationStatus + { + IsOK = true, + Message = "Update successfully", + ReturnValue = Convert.ToString(idCard) + }); } } diff --git a/Scrummer/Scripts/05. Cards.js b/Scrummer/Scripts/05. Cards.js index 335edd4..08683d7 100644 --- a/Scrummer/Scripts/05. Cards.js +++ b/Scrummer/Scripts/05. Cards.js @@ -1,4 +1,120 @@ -var Card = function (cfg, idCard, title, body, x, y) { +var Toolbox = function (cfg, container) { + this.cfg = cfg; + this.X = 0; + this.Y = 0; + this.container = container; + + // Create DOM + this.divToolbox = document.createElement("div"); + this.divToolbox.className = "divToolbox"; + this.divToolbox.style.left = this.X + "px"; + this.divToolbox.style.top = this.Y + "px"; + + this.divTitle = document.createElement("div"); + this.divToolbox.appendChild(this.divTitle); + this.divTitle.className = "divTitle"; + this.divTitle.innerHTML = cfg.Texts.Toolbox; + + this.btnAdd = document.createElement("button"); + this.divToolbox.appendChild(this.btnAdd); + this.btnAdd.className = "btnToolbox"; + this.btnAdd.innerHTML = cfg.Texts.AddCard; + this.btnAdd.addEventListener("click", Toolbox.prototype.btnAdd_Click.bind(this), false); + + this.divOverlay = document.createElement("div"); + this.divToolbox.appendChild(this.divOverlay); + this.divOverlay.className = "divOverlay"; + + this.container.appendChild(this.divToolbox); + + // Bind mouse event handlers + this.bindedMouseDown = Toolbox.prototype.MouseDown.bind(this); + this.bindedMouseMove = Toolbox.prototype.MouseMove.bind(this); + this.bindedMouseUp = Toolbox.prototype.MouseUp.bind(this); + this.divOverlay.addEventListener("mousedown", this.bindedMouseDown, false); + + // Bind touch event handlers + this.bindedTouchStart = Toolbox.prototype.TouchStart.bind(this); + this.bindedTouchMove = Toolbox.prototype.TouchMove.bind(this); + this.bindedTouchEnd = Toolbox.prototype.TouchEnd.bind(this); + this.divOverlay.addEventListener("touchstart", this.bindedTouchStart, false); + + // temporal variables for dragging, editing and deleting + this.offsetX = 0; + this.offsetY = 0; +}; +Toolbox.prototype = { + GetRelativePosToContainer: function (pos) { + var tempElem = this.container; + var relPos = { x: pos.x, y: pos.y }; + while (tempElem) { + relPos.x -= tempElem.offsetLeft; + relPos.y -= tempElem.offsetTop; + tempElem = tempElem.offsetParent; + } + return relPos; + }, + MouseDown: function (evt) { + evt.preventDefault(); + var pos = this.GetRelativePosToContainer({ x: evt.clientX, y: evt.clientY }); + this.offsetX = pos.x - this.divToolbox.offsetLeft; + this.offsetY = pos.y - this.divToolbox.offsetTop; + document.addEventListener("mouseup", this.bindedMouseUp, false); + document.addEventListener("mousemove", this.bindedMouseMove, false); + return false; + }, + MouseMove: function (evt) { + evt.preventDefault(); + var pos = this.GetRelativePosToContainer({ x: evt.clientX, y: evt.clientY }); + this.divToolbox.style.left = parseInt(pos.x - this.offsetX) + "px"; + this.divToolbox.style.top = parseInt(pos.y - this.offsetY) + "px"; + return false; + }, + MouseUp: function (evt) { + evt.preventDefault(); + document.removeEventListener("mouseup", this.bindedMouseUp, false); + document.removeEventListener("mousemove", this.bindedMouseMove, false); + return false; + }, + TouchStart: function (evt) { + evt.preventDefault(); + var pos = this.GetRelativePosToContainer({ x: evt.touches[0].clientX, y: evt.touches[0].clientY }); + this.offsetX = pos.x - this.divToolbox.offsetLeft; + this.offsetY = pos.y - this.divToolbox.offsetTop; + document.addEventListener("touchend", this.bindedTouchEnd, false); + document.addEventListener("touchcancel", this.bindedTouchEnd, false); + document.addEventListener("touchmove", this.bindedTouchMove, false); + return false; + }, + TouchMove: function (evt) { + evt.preventDefault(); + var pos = this.GetRelativePosToContainer({ x: evt.touches[0].clientX, y: evt.touches[0].clientY }); + this.divToolbox.style.left = parseInt(pos.x - this.offsetX) + "px"; + this.divToolbox.style.top = parseInt(pos.y - this.offsetY) + "px"; + return false; + }, + TouchEnd: function (evt) { + evt.preventDefault(); + document.removeEventListener("touchend", this.bindedTouchEnd, false); + document.removeEventListener("touchcancel", this.bindedTouchEnd, false); + document.removeEventListener("touchmove", this.bindedTouchMove, false); + return false; + }, + btnAdd_Click: function (evt) { + evt.preventDefault(); + var pos = this.GetRelativePosToContainer({ x: 0, y: 0 }); + pos.x += this.divToolbox.offsetLeft; + pos.y += this.divToolbox.offsetTop + this.divToolbox.offsetHeight; + var card = new Card(this.cfg, 0, "", "", pos.x, pos.y); + //card.SetDeleteCallback(bindedCardDelete); + //cfg.Cards.push(card); + card.InsertInContainer(this.cfg.divBoard); + card.EnterEditionMode(); + return false; + } +}; + +var Card = function (cfg, idCard, title, body, x, y) { this.cfg = cfg; this.IDCard = idCard; this.Title = title; @@ -144,6 +260,7 @@ Card.prototype = { var card = this; if (this.cfg.Connected == false) { card.Reset(); + return; } var data = { "IDBoard": this.cfg.IDBoard, @@ -173,6 +290,7 @@ Card.prototype = { var card = this; if (this.cfg.Connected == false) { card.Reset(); + return; } var data = { "IDBoard": this.cfg.IDBoard, @@ -230,6 +348,36 @@ Card.prototype = { card.Show(); }); }, + OnCreate: function () { + var card = this; + if (this.cfg.Connected == false) { + card.OnDelete(); + return; + } + var data = { + "IDBoard": this.cfg.IDBoard, + "Command": "Create", + "X": this.X, + "Y": this.Y, + "Title": this.Title, + "Body": this.Body, + "TimeStamp": new Date().getTime() + }; + SendData(this.cfg.ServiceUrl, data, + function (responseText) { + try { + var recvData = JSON.parse(responseText); + if (recvData && recvData instanceof Object && recvData.IsOK == true) { + //card.IDCard = parseInt(recvData.ReturnValue); + card.OnDelete(); + } else { + card.OnDelete(); + } + } catch (e) { } + }, function () { + card.OnDelete(); + }); + }, GetRelativePosToContainer: function (pos) { var tempElem = this.container; var relPos = { x: pos.x, y: pos.y }; @@ -342,18 +490,27 @@ Card.prototype = { this.ExitEditionMode(); this.divTitle.innerHTML = this.FilterText(this.newTitle); this.divBody.innerHTML = this.FilterText(this.newBody); - this.OnEdit(); + if (this.IDCard > 0) { + this.OnEdit(); + } else { + this.Title = this.newTitle; + this.Body = this.newBody; + this.OnCreate(); + } return false; }, btnCancelEdit_Click: function (evt) { evt.preventDefault(); this.ExitEditionMode(); this.Reset(); + if (this.IDCard == 0) { + this.OnDelete(); + } return false; }, btnDelete_Click: function (evt) { evt.preventDefault(); - if (confirm(this.cfg.Texts.ConfirmDelete)) { + if (this.IDCard==0 || confirm(this.cfg.Texts.ConfirmDelete)) { this.OnDelete(); } return false; @@ -363,6 +520,8 @@ Card.prototype = { function RunCardBoard(cfg) { cfg.divBoard = GetElement(cfg.divBoard); + cfg.Toolbox = new Toolbox(cfg, cfg.divBoard); + cfg.Connected = false; cfg.Cards = []; diff --git a/Scrummer/Styles/05. Cards.css b/Scrummer/Styles/05. Cards.css index bdfac31..814511d 100644 --- a/Scrummer/Styles/05. Cards.css +++ b/Scrummer/Styles/05. Cards.css @@ -1,4 +1,55 @@ -.divCard{ +.divToolbox{ + position: absolute; + background-color: rgb(127,127,255); + box-shadow: 0 0 10px rgba(0,0,0,0.5); + min-width: 150px; + min-height: 50px; + padding: 5px; + border-radius: 2px; +} + +.divToolbox .divTitle{ + font-family: "Segoe UI",Tahoma,Geneva,Verdana,sans-serif; + font-size: 12px; + font-weight: bold; + text-align: center; + display: block; + height: 20px; + line-height: 20px; + background-color: rgb(0,0,128); + color: rgb(128,128,255); + border-radius: 3px; + margin-bottom: 5px; +} + +.divToolbox .divOverlay{ + opacity: 0; + background-color: rgb(127,127,255); + position: absolute; + top: 0; + left: 0; + right: 0; + height:30px; +} + +.divToolbox .btnToolbox{ + margin-top: 5px; + margin-right: 5px; + padding: 2px; + border:solid 1px rgb(0,0,128); + border-radius: 3px; + color: rgb(0,0,128); + background-color: transparent; + font-family: "Segoe UI",Tahoma,Geneva,Verdana,sans-serif; + font-size: 12px; +} +.divToolbox .btnToolbox:hover{ + color: rgb(127,127,255); + background-color: rgb(0,0,128); +} + + +.divCard{ position: absolute; background-color: rgb(255,255,0); box-shadow: 0 0 10px rgba(0,0,0,0.5); @@ -36,6 +87,7 @@ margin-right: 5px; padding: 2px; border:solid 1px black; + border-radius: 3px; color: black; background-color: transparent; font-family: "Segoe UI",Tahoma,Geneva,Verdana,sans-serif;