選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

712 行
24 KiB

  1. /*
  2. Copyright (c) 2012-2017 Open Lab
  3. Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
  4. Permission is hereby granted, free of charge, to any person obtaining
  5. a copy of this software and associated documentation files (the
  6. "Software"), to deal in the Software without restriction, including
  7. without limitation the rights to use, copy, modify, merge, publish,
  8. distribute, sublicense, and/or sell copies of the Software, and to
  9. permit persons to whom the Software is furnished to do so, subject to
  10. the following conditions:
  11. The above copyright notice and this permission notice shall be
  12. included in all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  17. LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  18. OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  19. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. */
  21. function GridEditor(master) {
  22. this.master = master; // is the a GantEditor instance
  23. var editorTabel = $.JST.createFromTemplate({}, "TASKSEDITHEAD");
  24. if (!master.permissions.canSeeDep)
  25. editorTabel.find(".requireCanSeeDep").hide();
  26. this.gridified = $.gridify(editorTabel);
  27. this.element = this.gridified.find(".gdfTable").eq(1);
  28. }
  29. GridEditor.prototype.fillEmptyLines = function () {
  30. //console.debug("fillEmptyLines")
  31. var factory = new TaskFactory();
  32. var master = this.master;
  33. //console.debug("GridEditor.fillEmptyLines");
  34. var rowsToAdd = master.minRowsInEditor - this.element.find(".taskEditRow").length;
  35. var empty=this.element.find(".emptyRow").length;
  36. rowsToAdd=Math.max(rowsToAdd,empty>5?0:5-empty);
  37. //fill with empty lines
  38. for (var i = 0; i < rowsToAdd; i++) {
  39. var emptyRow = $.JST.createFromTemplate({}, "TASKEMPTYROW");
  40. if (!master.permissions.canSeeDep)
  41. emptyRow.find(".requireCanSeeDep").hide();
  42. //click on empty row create a task and fill above
  43. emptyRow.click(function (ev) {
  44. //console.debug("emptyRow.click")
  45. var emptyRow = $(this);
  46. //add on the first empty row only
  47. if (!master.permissions.canWrite || !master.permissions.canAdd || emptyRow.prevAll(".emptyRow").length > 0)
  48. return;
  49. master.beginTransaction();
  50. var lastTask;
  51. var start = new Date().getTime();
  52. var level = 0;
  53. if (master.tasks[0]) {
  54. start = master.tasks[0].start;
  55. level = master.tasks[0].level + 1;
  56. }
  57. //fill all empty previouses
  58. var cnt=0;
  59. emptyRow.prevAll(".emptyRow").addBack().each(function () {
  60. cnt++;
  61. var ch = factory.build("tmp_fk" + new Date().getTime()+"_"+cnt, "", "", level, start, 1);
  62. var task = master.addTask(ch);
  63. lastTask = ch;
  64. });
  65. master.endTransaction();
  66. if (lastTask.rowElement) {
  67. //lastTask.rowElement.click(); removed R&S 22/03/2016 il click è bindato comunque
  68. lastTask.rowElement.find("[name=name]").focus();//focus to "name" input
  69. }
  70. });
  71. this.element.append(emptyRow);
  72. }
  73. };
  74. GridEditor.prototype.addTask = function (task, row, hideIfParentCollapsed) {
  75. //console.debug("GridEditor.addTask",task,row);
  76. //var prof = new Profiler("editorAddTaskHtml");
  77. //remove extisting row
  78. this.element.find("[taskId=" + task.id + "]").remove();
  79. var taskRow = $.JST.createFromTemplate(task, "TASKROW");
  80. if (!this.master.permissions.canSeeDep)
  81. taskRow.find(".requireCanSeeDep").hide();
  82. if (!this.master.permissions.canSeePopEdit)
  83. taskRow.find(".edit .teamworkIcon").hide();
  84. //save row element on task
  85. task.rowElement = taskRow;
  86. this.bindRowEvents(task, taskRow);
  87. if (typeof(row) != "number") {
  88. var emptyRow = this.element.find(".emptyRow:first"); //tries to fill an empty row
  89. if (emptyRow.length > 0)
  90. emptyRow.replaceWith(taskRow);
  91. else
  92. this.element.append(taskRow);
  93. } else {
  94. var tr = this.element.find("tr.taskEditRow").eq(row);
  95. if (tr.length > 0) {
  96. tr.before(taskRow);
  97. } else {
  98. this.element.append(taskRow);
  99. }
  100. }
  101. //[expand]
  102. if (hideIfParentCollapsed) {
  103. if (task.collapsed) taskRow.addClass('collapsed');
  104. var collapsedDescendant = this.master.getCollapsedDescendant();
  105. if (collapsedDescendant.indexOf(task) >= 0) taskRow.hide();
  106. }
  107. return taskRow;
  108. };
  109. GridEditor.prototype.refreshExpandStatus = function (task) {
  110. //console.debug("refreshExpandStatus",task);
  111. if (!task) return;
  112. if (task.isParent()) {
  113. task.rowElement.addClass("isParent");
  114. } else {
  115. task.rowElement.removeClass("isParent");
  116. }
  117. var par = task.getParent();
  118. if (par && !par.rowElement.is("isParent")) {
  119. par.rowElement.addClass("isParent");
  120. }
  121. };
  122. GridEditor.prototype.refreshTaskRow = function (task) {
  123. //console.debug("refreshTaskRow")
  124. //var profiler = new Profiler("editorRefreshTaskRow");
  125. var row = task.rowElement;
  126. row.find(".taskRowIndex").html(task.getRow() + 1);
  127. row.find(".indentCell").css("padding-left", task.level * 10 + 18);
  128. row.find("[name=name]").val(task.name);
  129. row.find("[name=code]").val(task.code);
  130. row.find("[status]").attr("status", task.status);
  131. row.find("[name=duration]").val(task.duration);
  132. row.find("[name=progress]").val(task.progress).prop("readonly",task.progressByWorklog==true);
  133. row.find("[name=startIsMilestone]").prop("checked", task.startIsMilestone);
  134. row.find("[name=start]").val(new Date(task.start).format()).updateOldValue().prop("readonly",task.depends || !task.canWrite && !this.master.permissions.canWrite ); // called on dates only because for other field is called on focus event
  135. row.find("[name=endIsMilestone]").prop("checked", task.endIsMilestone);
  136. row.find("[name=end]").val(new Date(task.end).format()).updateOldValue();
  137. row.find("[name=depends]").val(task.depends);
  138. row.find(".taskAssigs").html(task.getAssigsString());
  139. //manage collapsed
  140. if (task.collapsed)
  141. row.addClass("collapsed");
  142. else
  143. row.removeClass("collapsed");
  144. //Enhancing the function to perform own operations
  145. this.master.element.trigger('gantt.task.afterupdate.event', task);
  146. //profiler.stop();
  147. };
  148. GridEditor.prototype.redraw = function () {
  149. //console.debug("GridEditor.prototype.redraw")
  150. for (var i = 0; i < this.master.tasks.length; i++) {
  151. this.refreshTaskRow(this.master.tasks[i]);
  152. }
  153. // check if new emty rows are needed
  154. if (this.master.fillWithEmptyLines)
  155. this.fillEmptyLines();
  156. };
  157. GridEditor.prototype.reset = function () {
  158. this.element.find("[taskid]").remove();
  159. };
  160. GridEditor.prototype.bindRowEvents = function (task, taskRow) {
  161. var self = this;
  162. //console.debug("bindRowEvents",this,this.master,this.master.permissions.canWrite, task.canWrite);
  163. if (this.master.permissions.canWrite && task.canWrite) {
  164. self.bindRowInputEvents(task, taskRow);
  165. } else { //cannot write: disable input
  166. taskRow.find("input").prop("readonly", true);
  167. taskRow.find("input:checkbox,select").prop("disabled", true);
  168. }
  169. if (!this.master.permissions.canSeeDep)
  170. taskRow.find("[name=depends]").attr("readonly", true);
  171. self.bindRowExpandEvents(task, taskRow);
  172. if (this.master.permissions.canSeePopEdit) {
  173. taskRow.find(".edit").click(function () {self.openFullEditor(task, taskRow, false)});
  174. taskRow.find(".taskAssigs").dblclick(function () {self.openFullEditor(task, taskRow, true)});
  175. }
  176. };
  177. GridEditor.prototype.bindRowExpandEvents = function (task, taskRow) {
  178. var self = this;
  179. //expand collapse
  180. taskRow.find(".exp-controller").click(function () {
  181. var el = $(this);
  182. var taskId = el.closest("[taskid]").attr("taskid");
  183. var task = self.master.getTask(taskId);
  184. if (task.collapsed) {
  185. self.master.expand(task,false);
  186. } else {
  187. self.master.collapse(task,false);
  188. }
  189. });
  190. };
  191. GridEditor.prototype.bindRowInputEvents = function (task, taskRow) {
  192. var self = this;
  193. //bind dateField on dates
  194. taskRow.find(".date").each(function () {
  195. var el = $(this);
  196. el.click(function () {
  197. var inp = $(this);
  198. inp.dateField({
  199. inputField: el,
  200. callback: function (d) {
  201. $(this).blur();
  202. }
  203. });
  204. });
  205. el.blur(function (date) {
  206. var inp = $(this);
  207. if (inp.isValueChanged()) {
  208. if (!Date.isValid(inp.val())) {
  209. alert(GanttMaster.messages["INVALID_DATE_FORMAT"]);
  210. inp.val(inp.getOldValue());
  211. } else {
  212. var row = inp.closest("tr");
  213. var taskId = row.attr("taskId");
  214. var task = self.master.getTask(taskId);
  215. var leavingField = inp.prop("name");
  216. var dates = resynchDates(inp, row.find("[name=start]"), row.find("[name=startIsMilestone]"), row.find("[name=duration]"), row.find("[name=end]"), row.find("[name=endIsMilestone]"));
  217. //console.debug("resynchDates",new Date(dates.start), new Date(dates.end),dates.duration)
  218. //update task from editor
  219. self.master.beginTransaction();
  220. self.master.changeTaskDates(task, dates.start, dates.end);
  221. self.master.endTransaction();
  222. inp.updateOldValue(); //in order to avoid multiple call if nothing changed
  223. }
  224. }
  225. });
  226. });
  227. //milestones checkbox
  228. taskRow.find(":checkbox").click(function () {
  229. var el = $(this);
  230. var row = el.closest("tr");
  231. var taskId = row.attr("taskId");
  232. var task = self.master.getTask(taskId);
  233. //update task from editor
  234. var field = el.prop("name");
  235. if (field == "startIsMilestone" || field == "endIsMilestone") {
  236. self.master.beginTransaction();
  237. //milestones
  238. task[field] = el.prop("checked");
  239. resynchDates(el, row.find("[name=start]"), row.find("[name=startIsMilestone]"), row.find("[name=duration]"), row.find("[name=end]"), row.find("[name=endIsMilestone]"));
  240. self.master.endTransaction();
  241. }
  242. });
  243. //binding on blur for task update (date exluded as click on calendar blur and then focus, so will always return false, its called refreshing the task row)
  244. taskRow.find("input:text:not(.date)").focus(function () {
  245. $(this).updateOldValue();
  246. }).blur(function (event) {
  247. var el = $(this);
  248. var row = el.closest("tr");
  249. var taskId = row.attr("taskId");
  250. var task = self.master.getTask(taskId);
  251. //update task from editor
  252. var field = el.prop("name");
  253. //console.debug("blur",field)
  254. if (el.isValueChanged()) {
  255. self.master.beginTransaction();
  256. if (field == "depends") {
  257. var oldDeps = task.depends;
  258. task.depends = el.val();
  259. // update links
  260. var linkOK = self.master.updateLinks(task);
  261. if (linkOK) {
  262. //synchronize status from superiors states
  263. var sups = task.getSuperiors();
  264. /*
  265. for (var i = 0; i < sups.length; i++) {
  266. if (!sups[i].from.synchronizeStatus())
  267. break;
  268. }
  269. */
  270. var oneFailed=false;
  271. var oneUndefined=false;
  272. var oneActive=false;
  273. var oneSuspended=false;
  274. for (var i = 0; i < sups.length; i++) {
  275. oneFailed=oneFailed|| sups[i].from.status=="STATUS_FAILED";
  276. oneUndefined=oneUndefined|| sups[i].from.status=="STATUS_UNDEFINED";
  277. oneActive=oneActive|| sups[i].from.status=="STATUS_ACTIVE";
  278. oneSuspended=oneSuspended|| sups[i].from.status=="STATUS_SUSPENDED";
  279. }
  280. if (oneFailed){
  281. task.changeStatus("STATUS_FAILED")
  282. } else if (oneUndefined){
  283. task.changeStatus("STATUS_UNDEFINED")
  284. } else if (oneActive){
  285. task.changeStatus("STATUS_SUSPENDED")
  286. } else if (oneSuspended){
  287. task.changeStatus("STATUS_SUSPENDED")
  288. } else {
  289. task.changeStatus("STATUS_ACTIVE")
  290. }
  291. self.master.changeTaskDeps(task); //dates recomputation from dependencies
  292. }
  293. } else if (field == "duration") {
  294. var dates = resynchDates(el, row.find("[name=start]"), row.find("[name=startIsMilestone]"), row.find("[name=duration]"), row.find("[name=end]"), row.find("[name=endIsMilestone]"));
  295. self.master.changeTaskDates(task, dates.start, dates.end);
  296. } else if (field == "name" && el.val() == "") { // remove unfilled task
  297. task.deleteTask();
  298. self.master.gantt.synchHighlight();
  299. } else if (field == "progress" ) {
  300. task[field]=parseFloat(el.val())||0;
  301. el.val(task[field]);
  302. } else {
  303. task[field] = el.val();
  304. }
  305. self.master.endTransaction();
  306. } else if (field == "name" && el.val() == "") { // remove unfilled task even if not changed
  307. if (task.getRow()!=0) {
  308. task.deleteTask();
  309. self.master.gantt.synchHighlight();
  310. }else {
  311. el.oneTime(1,"foc",function(){$(this).focus()}); //
  312. event.preventDefault();
  313. //return false;
  314. }
  315. }
  316. });
  317. //cursor key movement
  318. taskRow.find("input").keydown(function (event) {
  319. var theCell = $(this);
  320. var theTd = theCell.parent();
  321. var theRow = theTd.parent();
  322. var col = theTd.prevAll("td").length;
  323. var ret = true;
  324. if (!event.ctrlKey) {
  325. switch (event.keyCode) {
  326. case 37: //left arrow
  327. if (!theCell.is(":text") || (!this.selectionEnd || this.selectionEnd == 0))
  328. theTd.prev().find("input").focus();
  329. break;
  330. case 39: //right arrow
  331. if (!theCell.is(":text") || (!this.selectionEnd || this.selectionEnd == this.value.length))
  332. theTd.next().find("input").focus();
  333. break;
  334. case 38: //up arrow
  335. //var prevRow = theRow.prev();
  336. var prevRow = theRow.prevAll(":visible:first");
  337. var td = prevRow.find("td").eq(col);
  338. var inp = td.find("input");
  339. if (inp.length > 0)
  340. inp.focus();
  341. break;
  342. case 40: //down arrow
  343. //var nextRow = theRow.next();
  344. var nextRow = theRow.nextAll(":visible:first");
  345. var td = nextRow.find("td").eq(col);
  346. var inp = td.find("input");
  347. if (inp.length > 0)
  348. inp.focus();
  349. else
  350. nextRow.click(); //create a new row
  351. break;
  352. case 36: //home
  353. break;
  354. case 35: //end
  355. break;
  356. case 9: //tab
  357. case 13: //enter
  358. break;
  359. }
  360. }
  361. return ret;
  362. }).focus(function () {
  363. $(this).closest("tr").click();
  364. });
  365. //change status
  366. taskRow.find(".taskStatus").click(function () {
  367. var el = $(this);
  368. var tr = el.closest("[taskid]");
  369. var taskId = tr.attr("taskid");
  370. var task = self.master.getTask(taskId);
  371. var changer = $.JST.createFromTemplate({}, "CHANGE_STATUS");
  372. changer.find("[status=" + task.status + "]").addClass("selected");
  373. changer.find(".taskStatus").click(function (e) {
  374. e.stopPropagation();
  375. var newStatus = $(this).attr("status");
  376. changer.remove();
  377. self.master.beginTransaction();
  378. task.changeStatus(newStatus);
  379. self.master.endTransaction();
  380. el.attr("status", task.status);
  381. });
  382. el.oneTime(3000, "hideChanger", function () {
  383. changer.remove();
  384. });
  385. el.after(changer);
  386. });
  387. //bind row selection
  388. taskRow.click(function (event) {
  389. var row = $(this);
  390. //console.debug("taskRow.click",row.attr("taskid"),event.target)
  391. //var isSel = row.hasClass("rowSelected");
  392. row.closest("table").find(".rowSelected").removeClass("rowSelected");
  393. row.addClass("rowSelected");
  394. //set current task
  395. self.master.currentTask = self.master.getTask(row.attr("taskId"));
  396. //move highlighter
  397. self.master.gantt.synchHighlight();
  398. //if offscreen scroll to element
  399. var top = row.position().top;
  400. if (top > self.element.parent().height()) {
  401. row.offsetParent().scrollTop(top - self.element.parent().height() + 100);
  402. } else if (top <= 40) {
  403. row.offsetParent().scrollTop(row.offsetParent().scrollTop() - 40 + top);
  404. }
  405. });
  406. };
  407. GridEditor.prototype.openFullEditor = function (task, taskRow, editOnlyAssig) {
  408. var self = this;
  409. if (!self.master.permissions.canSeePopEdit)
  410. return;
  411. //task editor in popup
  412. var taskId = taskRow.attr("taskId");
  413. //console.debug(task);
  414. //make task editor
  415. var taskEditor = $.JST.createFromTemplate(task, "TASK_EDITOR");
  416. //hide task data if editing assig only
  417. if (editOnlyAssig) {
  418. taskEditor.find(".taskData").hide();
  419. taskEditor.find(".assigsTableWrapper").height(455);
  420. taskEditor.prepend("<h1>\""+task.name+"\"</h1>");
  421. }
  422. //got to extended editor
  423. if (task.isNew()|| !self.master.permissions.canSeeFullEdit){
  424. taskEditor.find("#taskFullEditor").remove();
  425. } else {
  426. taskEditor.bind("openFullEditor.gantt",function () {
  427. window.location.href=contextPath+"/applications/teamwork/task/taskEditor.jsp?CM=ED&OBJID="+task.id;
  428. });
  429. }
  430. taskEditor.find("#name").val(task.name);
  431. taskEditor.find("#description").val(task.description);
  432. taskEditor.find("#code").val(task.code);
  433. taskEditor.find("#progress").val(task.progress ? parseFloat(task.progress) : 0).prop("readonly",task.progressByWorklog==true);
  434. taskEditor.find("#progressByWorklog").prop("checked",task.progressByWorklog);
  435. taskEditor.find("#status").val(task.status);
  436. taskEditor.find("#type").val(task.typeId);
  437. taskEditor.find("#type_txt").val(task.type);
  438. taskEditor.find("#relevance").val(task.relevance);
  439. //cvc_redraw(taskEditor.find(".cvcComponent"));
  440. if (task.startIsMilestone)
  441. taskEditor.find("#startIsMilestone").prop("checked", true);
  442. if (task.endIsMilestone)
  443. taskEditor.find("#endIsMilestone").prop("checked", true);
  444. taskEditor.find("#duration").val(task.duration);
  445. var startDate = taskEditor.find("#start");
  446. startDate.val(new Date(task.start).format());
  447. //start is readonly in case of deps
  448. if (task.depends || !this.master.permissions.canWrite && !task.canWrite) {
  449. startDate.attr("readonly", "true");
  450. } else {
  451. startDate.removeAttr("readonly");
  452. }
  453. taskEditor.find("#end").val(new Date(task.end).format());
  454. //make assignments table
  455. var assigsTable = taskEditor.find("#assigsTable");
  456. assigsTable.find("[assId]").remove();
  457. // loop on assignments
  458. for (var i = 0; i < task.assigs.length; i++) {
  459. var assig = task.assigs[i];
  460. var assigRow = $.JST.createFromTemplate({task: task, assig: assig}, "ASSIGNMENT_ROW");
  461. assigsTable.append(assigRow);
  462. }
  463. if (!self.master.permissions.canWrite || !task.canWrite) {
  464. taskEditor.find("input,textarea").prop("readOnly", true);
  465. taskEditor.find("input:checkbox,select").prop("disabled", true);
  466. taskEditor.find("#saveButton").remove();
  467. taskEditor.find(".button").addClass("disabled");
  468. } else {
  469. //bind dateField on dates, duration
  470. taskEditor.find("#start,#end,#duration").click(function () {
  471. var input = $(this);
  472. if (input.is("[entrytype=DATE]")) {
  473. input.dateField({
  474. inputField: input,
  475. callback: function (d) {$(this).blur();}
  476. });
  477. }
  478. }).blur(function () {
  479. var inp = $(this);
  480. if (inp.validateField()) {
  481. resynchDates(inp, taskEditor.find("[name=start]"), taskEditor.find("[name=startIsMilestone]"), taskEditor.find("[name=duration]"), taskEditor.find("[name=end]"), taskEditor.find("[name=endIsMilestone]"));
  482. //workload computation
  483. if (typeof(workloadDatesChanged)=="function")
  484. workloadDatesChanged();
  485. }
  486. });
  487. taskEditor.find("#startIsMilestone,#endIsMilestone").click(function () {
  488. var inp = $(this);
  489. resynchDates(inp, taskEditor.find("[name=start]"), taskEditor.find("[name=startIsMilestone]"), taskEditor.find("[name=duration]"), taskEditor.find("[name=end]"), taskEditor.find("[name=endIsMilestone]"));
  490. });
  491. //bind add assignment
  492. var cnt=0;
  493. taskEditor.find("#addAssig").click(function () {
  494. cnt++;
  495. var assigsTable = taskEditor.find("#assigsTable");
  496. var assigRow = $.JST.createFromTemplate({task: task, assig: {id: "tmp_" + new Date().getTime()+"_"+cnt}}, "ASSIGNMENT_ROW");
  497. assigsTable.append(assigRow);
  498. $("#bwinPopupd").scrollTop(10000);
  499. }).click();
  500. //save task
  501. taskEditor.bind("saveFullEditor.gantt",function () {
  502. //console.debug("saveFullEditor");
  503. var task = self.master.getTask(taskId); // get task again because in case of rollback old task is lost
  504. self.master.beginTransaction();
  505. task.name = taskEditor.find("#name").val();
  506. task.description = taskEditor.find("#description").val();
  507. task.code = taskEditor.find("#code").val();
  508. task.progress = parseFloat(taskEditor.find("#progress").val());
  509. //task.duration = parseInt(taskEditor.find("#duration").val()); //bicch rimosso perchè devono essere ricalcolata dalla start end, altrimenti sbaglia
  510. task.startIsMilestone = taskEditor.find("#startIsMilestone").is(":checked");
  511. task.endIsMilestone = taskEditor.find("#endIsMilestone").is(":checked");
  512. task.type = taskEditor.find("#type_txt").val();
  513. task.typeId = taskEditor.find("#type").val();
  514. task.relevance = taskEditor.find("#relevance").val();
  515. task.progressByWorklog= taskEditor.find("#progressByWorklog").is(":checked");
  516. //set assignments
  517. var cnt=0;
  518. taskEditor.find("tr[assId]").each(function () {
  519. var trAss = $(this);
  520. var assId = trAss.attr("assId");
  521. var resId = trAss.find("[name=resourceId]").val();
  522. var resName = trAss.find("[name=resourceId_txt]").val(); // from smartcombo text input part
  523. var roleId = trAss.find("[name=roleId]").val();
  524. var effort = millisFromString(trAss.find("[name=effort]").val(),true);
  525. //check if the selected resource exists in ganttMaster.resources
  526. var res= self.master.getOrCreateResource(resId,resName);
  527. //if resource is not found nor created
  528. if (!res)
  529. return;
  530. //check if an existing assig has been deleted and re-created with the same values
  531. var found = false;
  532. for (var i = 0; i < task.assigs.length; i++) {
  533. var ass = task.assigs[i];
  534. if (assId == ass.id) {
  535. ass.effort = effort;
  536. ass.roleId = roleId;
  537. ass.resourceId = res.id;
  538. ass.touched = true;
  539. found = true;
  540. break;
  541. } else if (roleId == ass.roleId && res.id == ass.resourceId) {
  542. ass.effort = effort;
  543. ass.touched = true;
  544. found = true;
  545. break;
  546. }
  547. }
  548. if (!found && resId && roleId) { //insert
  549. cnt++;
  550. //console.debug("adding assig row:", assId,resId,resName,roleId,effort)
  551. var ass = task.createAssignment("tmp_" + new Date().getTime()+"_"+cnt, resId, roleId, effort);
  552. ass.touched = true;
  553. }
  554. });
  555. //console.debug("task.assigs",task.assigs,task.assigs.length)
  556. //remove untouched assigs
  557. task.assigs = task.assigs.filter(function (ass) {
  558. var ret = ass.touched;
  559. delete ass.touched;
  560. return ret;
  561. });
  562. //console.debug("task.assigs",task.assigs,task.assigs.length)
  563. //change dates
  564. task.setPeriod(Date.parseString(taskEditor.find("#start").val()).getTime(), Date.parseString(taskEditor.find("#end").val()).getTime() + (3600000 * 22));
  565. //change status
  566. task.changeStatus(taskEditor.find("#status").val());
  567. if (self.master.endTransaction()) {
  568. taskEditor.find(":input").updateOldValue();
  569. closeBlackPopup();
  570. }
  571. });
  572. }
  573. taskEditor.attr("alertonchange","true");
  574. var ndo = createModalPopup(800, 450).append(taskEditor);//.append("<div style='height:800px; background-color:red;'></div>")
  575. //var ndo = createModalPopup(800, 650).append("<div style='height:300px; background-color:red;'></div>")
  576. //workload computation
  577. if (typeof(workloadDatesChanged)=="function")
  578. workloadDatesChanged();
  579. };