Chorem-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
June 2013
- 5 participants
- 22 discussions
r347 - in trunk/chorem-webmotion/src/main: java/org/chorem/webmotion/actions/project resources webapp/WEB-INF/jsp webapp/css webapp/img webapp/img/jquery.fn.gantt webapp/js
by meynier@users.chorem.org 26 Jun '13
by meynier@users.chorem.org 26 Jun '13
26 Jun '13
Author: meynier
Date: 2013-06-26 11:30:51 +0200 (Wed, 26 Jun 2013)
New Revision: 347
Url: http://chorem.org/projects/chorem/repository/revisions/347
Log:
Added gantt diagram in project dashboard with modified jquery.fn.gantt library
Added:
trunk/chorem-webmotion/src/main/webapp/css/jquery.fn.gantt.css
trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/
trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/grid.png
trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/icon_sprite.png
trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/loader_bg.png
trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/slider_handle.png
trunk/chorem-webmotion/src/main/webapp/js/jquery.fn.gantt.js
Removed:
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/
Modified:
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/Extensions.java
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java
trunk/chorem-webmotion/src/main/resources/mapping
trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp
trunk/chorem-webmotion/src/main/webapp/js/chorem.js
Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-06-25 09:55:33 UTC (rev 346)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-06-26 09:30:51 UTC (rev 347)
@@ -1,6 +1,8 @@
package org.chorem.webmotion.actions.project;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
@@ -19,6 +21,7 @@
import org.nuiton.wikitty.query.WikittyQuery;
import org.nuiton.wikitty.query.WikittyQueryMaker;
import org.nuiton.wikitty.query.WikittyQueryResult;
+import com.google.gson.*;
/**
*
* @author meynier
@@ -35,6 +38,8 @@
WikittyQueryResult<Quotation> quotationResult = null;
WikittyQueryResult<Task> taskResult = null;
HashMap<Quotation, List<Task>> taskMap = new HashMap<Quotation, List<Task>>();
+
+ HashMap<Quotation, String> jSonTaskMap = new HashMap<Quotation, String>();
//HashMap<Quotation, String> extMap = new HashMap<Quotation, String>();
//Fetch the project form the name (if it has been requested)
@@ -68,8 +73,16 @@
taskResult = client.findAllByQuery(Task.class, taskQuery);
taskMap.put(quote, taskResult.getAll());
-
-
+ List<JTask> lTask = new ArrayList<JTask>();
+ for(Task t : taskResult.getAll()) {
+ Values[] v = new Values[1];
+ v[0] = new Values(t.getBeginDate(), t.getEndDate(), t.getName(), "ganttRed");
+ JTask jt = new JTask(t.getName(), t.getDescription(), v);
+
+ lTask.add(jt);
+ }
+ Gson g = new Gson();
+ jSonTaskMap.put(quote, g.toJson(lTask));
}
}
@@ -89,7 +102,7 @@
else {
return renderView("dashboardSingleProject.jsp",
"title", "Tableau de bord projet", "projects", projectResult.getAll(),
- "quotations", quotationResult.getAll(), "taskMap", taskMap, "extensions",
+ "quotations", quotationResult.getAll(), "taskMap", taskMap,"jSonTaskMap",jSonTaskMap, "extensions",
Extensions.extensions);
}
}
@@ -121,4 +134,29 @@
return null;
}*/
+
+ private class JTask {
+ private String name;
+ private String desc;
+ private Values[] values;
+ public JTask(String name, String desc, Values[] values) {
+ this.name = name;
+ this.desc = desc;
+ this.values = values;
+ }
+
+ }
+ private class Values{
+ private String from;
+ private String to;
+ private String label;
+ private String customClass;
+ public Values(Date from, Date to, String label, String customClass) {
+ this.from = "/Date(" + from.getTime() + ")/";
+ this.to = "/Date(" + to.getTime() + ")/";
+ this.label = label;
+ this.customClass = customClass;
+ }
+
+ }
}
Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/Extensions.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/Extensions.java 2013-06-25 09:55:33 UTC (rev 346)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/Extensions.java 2013-06-26 09:30:51 UTC (rev 347)
@@ -11,6 +11,7 @@
"Delivered",
"RSV",
"Warranty",
- "Closed"
+ "Closed",
+ "Cancelled"
};
}
Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java 2013-06-25 09:55:33 UTC (rev 346)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java 2013-06-26 09:30:51 UTC (rev 347)
@@ -69,7 +69,7 @@
c.add(extensionName);
Wikitty wikitty = client.restore(id);
List<WikittyExtension> extensions = client.restoreExtensionAndDependenciesLastVesion(c);
-
+ System.out.println(extensions);
extensions.removeAll(wikitty.getExtensions());
Modified: trunk/chorem-webmotion/src/main/resources/mapping
===================================================================
--- trunk/chorem-webmotion/src/main/resources/mapping 2013-06-25 09:55:33 UTC (rev 346)
+++ trunk/chorem-webmotion/src/main/resources/mapping 2013-06-26 09:30:51 UTC (rev 347)
@@ -10,6 +10,7 @@
* /wikitty-json/* DecoratorFilter.decorate wmDecoratorNo=true
* /fragment/* DecoratorFilter.decorate wmDecoratorNo=true
* /sales/funnel/json/* DecoratorFilter.decorate wmDecoratorNo=true
+* /project/json/* DecoratorFilter.decorate wmDecoratorNo=true
GET /* DecoratorFilter.decorate
* /* AuthenticationFilter.check
#####
Modified: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-06-25 09:55:33 UTC (rev 346)
+++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-06-26 09:30:51 UTC (rev 347)
@@ -26,6 +26,8 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%>
+
+<link rel="stylesheet" href="<c:url value='/css/jquery.fn.gantt.css'/>" />
<h1>${title}</h1>
<form class="well form-inline" method="GET" id="projectSearch">
@@ -70,7 +72,7 @@
-
+<script>var ganttData = new Array();</script>
<c:forEach var="q" items="${quotations}">
<table class="table table-striped table-bordered table-condensed">
<thead>
@@ -104,9 +106,6 @@
fqfield="Quotation.amount" label="" /></td>
</tr>
</tbody>
-
-
-
</table>
@@ -116,9 +115,43 @@
<w:display wikitty="${q.wikitty}" fqfield="Interval.endDate"
label="" />
</p>
+ <a class="ganttinit" wikittyId="${q.wikittyId}" href="#">Afficher Gantt</a>
+ <div class="gantt-${q.wikittyId}" data =''></div>
+
+ <c:set var="script" value="ganttData['${q.wikittyId}'] = {src:${jSonTaskMap[q]},
+ startDate:'/Date(${q.beginDate.time})/',
+ endDate:'/Date(${q.endDate.time})/'
+ "/>
+
+ <%
+ java.util.HashMap<String,String> dateMap = new java.util.HashMap<String,String>();
+ dateMap.put("sendingDate", "Draft");
+ dateMap.put("postedDate", "Sent");
+ dateMap.put("acceptedDate", "Accepted");
+ dateMap.put("startedDate", "Started");
+ dateMap.put("deliveryDate", "Delivered");
+ dateMap.put("rsvStart", "RSV");
+ dateMap.put("warrantyStart", "Warranty");
+ dateMap.put("closedDate", "Closed");
+ dateMap.put("rejectedDate", "Rejected");
+ dateMap.put("cancelledDate", "Cancelled");
+ pageContext.setAttribute("dateMap", dateMap);
+ %>
+
+ <c:forEach items="${dateMap}" var="entry">
+ <c:if test='${q.wikitty.hasExtension(entry.value)}'>
+ <c:set var="script" value="${script},${entry.key} :'/Date(${q.wikitty.getFieldAsObject(entry.value, entry.key).time})/'"/>
+ </c:if>
+ </c:forEach>
+
+ <c:set var="script" value="${script}};"/>
+
+ <script>
+ ${script}
+ </script>
+
<p>Liste des tâches :</p>
<c:forEach items="${taskMap}" var="entry">
-
<c:if test="${entry.key.equals(q)}">
<ul>
<c:forEach items="${entry.value}" var="task">
@@ -133,53 +166,24 @@
</c:forEach>
<p>
- <select class="extBox" name="extList" wikittyId="${q.wikittyId}">
- <option>Transformer en...</option>
- <c:forEach items="${extensions}" var="ext">
-
- <c:set var="contains" value="false" />
- <c:forEach var="item" items="${q.extensionNames}">
- <c:if test="${item eq ext}">
- <c:set var="contains" value="true" />
+ <select class="extBox" name="extList" wikittyId="${q.wikittyId}">
+ <option>Transformer en...</option>
+ <c:forEach items="${extensions}" var="ext">
+ <c:set var="contains" value="false" />
+ <c:forEach var="item" items="${q.extensionNames}">
+ <c:if test="${item eq ext}">
+ <c:set var="contains" value="true" />
+ </c:if>
+ </c:forEach>
+ <c:if test="${contains == false}">
+ <option>${ext}</option>
</c:if>
</c:forEach>
-
- <c:if test="${contains == false}">
- <option>${ext}</option>
- </c:if>
-
- </c:forEach>
- </select>
+ </select>
</p>
- <div id="upgradeFields-${q.wikittyId}">
+ <div id="upgradeFields-${q.wikittyId}"></div>
+
- </div>
-
- <!--
-
- <form class="form-horizontal" method="post"
- accept-charset="ISO-8859-15"
- action="<c:url value="/wikitty/upgrade"/>"
- enctype="multipart/form-data">
- <input type="hidden" name="id" value="${q.wikittyId}">
- <c:if test="${extMap[q] != null}">
- <fieldset>
- <input type="hidden" name="extension" value="${extMap[q].name}">
- <c:forEach items="${extMap[q].fieldNames}" var="field">
- ${field}
- <div class="control-group">
- <label class="control-label">${fieldName}</label>
- <div class="controls">
- <w:input wikitty="${q.wikitty}"
- fqfield="${extMap[q].name}.${field}" extension="${extMap[q]}" />
- </div>
- </div>
- </c:forEach>
- <input type="submit" value="Tranformer en ${extMap[q].name}" />
- </fieldset>
- </c:if>
- </form>
- -->
</c:forEach>
</c:when>
@@ -197,9 +201,9 @@
+<script src="<c:url value='/js/jquery.fn.gantt.js'/>"></script>
-
Added: trunk/chorem-webmotion/src/main/webapp/css/jquery.fn.gantt.css
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/css/jquery.fn.gantt.css (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/css/jquery.fn.gantt.css 2013-06-26 09:30:51 UTC (rev 347)
@@ -0,0 +1,440 @@
+.gantt, .gantt2 {
+ width: 100%;
+ margin: 20px auto;
+ border: 14px solid #ddd;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.gantt:after {
+ content: ".";
+ visibility: hidden;
+ display: block;
+ height: 0;
+ clear: both;
+}
+
+.fn-gantt {
+ width: 100%;
+}
+
+.fn-gantt .fn-content {
+ overflow: hidden;
+ position: relative;
+ width: 100%;
+}
+
+
+
+
+/* === LEFT PANEL === */
+
+.fn-gantt .leftPanel {
+ float: left;
+ width: 225px;
+ overflow: hidden;
+ border-right: 1px solid #DDD;
+ position: relative;
+ z-index: 20;
+}
+
+.fn-gantt .row {
+ float: left;
+ height: 24px;
+ line-height: 24px;
+ margin-left: -24px;
+}
+
+.fn-gantt .leftPanel .fn-label {
+ display: inline-block;
+ margin: 0 0 0 5px;
+ color: #484A4D;
+ width: 110px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.fn-gantt .leftPanel .row0 {
+ border-top: 1px solid #DDD;
+}
+.fn-gantt .leftPanel .name, .fn-gantt .leftPanel .desc {
+ float: left;
+ height: 23px;
+ margin: 0;
+ border-bottom: 1px solid #DDD;
+ background-color: #f6f6f6;
+}
+
+.fn-gantt .leftPanel .name {
+ width: 110px;
+ font-weight: bold;
+}
+
+.fn-gantt .leftPanel .desc {
+ width: 115px;
+}
+
+.fn-gantt .leftPanel .fn-wide, .fn-gantt .leftPanel .fn-wide .fn-label {
+ width: 225px;
+}
+
+.fn-gantt .spacer {
+ margin: -2px 0 1px 0;
+ border-bottom: none;
+ background-color: #f6f6f6;
+}
+
+
+
+
+/* === RIGHT PANEL === */
+
+.fn-gantt .rightPanel {
+ overflow: hidden;
+}
+
+.fn-gantt .dataPanel {
+ margin-left: 0px;
+ border-right: 1px solid #DDD;
+ background-image: url(../img/jquery.fn.gantt/grid.png);
+ background-repeat: repeat;
+ background-position: 24px 24px;
+}
+.fn-gantt .day, .fn-gantt .date {
+ overflow: visible;
+ width: 24px;
+ line-height: 24px;
+ text-align: center;
+ border-left: 1px solid #DDD;
+ border-bottom: 1px solid #DDD;
+ margin: -1px 0 0 -1px;
+ font-size: 11px;
+ color: #484a4d;
+ text-shadow: 0 1px 0 rgba(255,255,255,0.75);
+ text-align: center;
+}
+
+.fn-gantt .holiday {
+ background-color: #ffd263;
+ height: 23px;
+ margin: 0 0 -1px -1px;
+}
+
+
+
+.fn-gantt .sa, .fn-gantt .sn, .fn-gantt .wd {
+ height: 23px;
+ margin: 0 0 0 -1px;
+ text-align: center;
+}
+
+.fn-gantt .sa, .fn-gantt .sn {
+ color: #939496;
+ background-color: #f5f5f5;
+ text-align: center;
+}
+
+.fn-gantt .wd {
+ background-color: #f6f6f6;
+ text-align: center;
+}
+
+.fn-gantt .today {
+ background-color: #fff8da;
+ height: 23px;
+ margin: 0 0 -1px -1px;
+ font-weight: bold;
+ text-align: center;
+}
+
+.fn-gantt .begin, .gn-gantt .end, .fn-gantt .event {
+ height: 23px;
+ margin: 0 0 -1px -1px;
+ font-weight: bold;
+ text-align: center;
+
+}
+
+.fn-gantt .begin {
+ background-color: #55cc11;
+}
+.fn-gantt .end {
+ background-color: #cc5511;
+}
+
+.fn-gantt .event {
+ background-color: #55aaee;
+}
+
+
+.fn-gantt .rightPanel .month, .fn-gantt .rightPanel .year {
+ float: left;
+ overflow: hidden;
+ border-left: 1px solid #DDD;
+ border-bottom: 1px solid #DDD;
+ height: 23px;
+ margin: 0 0 0 -1px;
+ background-color: #f6f6f6;
+ font-weight: bold;
+ font-size: 11px;
+ color: #484a4d;
+ text-shadow: 0 1px 0 rgba(255,255,255,0.75);
+ text-align: center;
+}
+
+.fn-gantt-hint {
+ border: 5px solid #edc332;
+ background-color: #fff5d4;
+ padding: 10px;
+ position: absolute;
+ display: none;
+ z-index: 20;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.fn-gantt .bar {
+ background-color: #D0E4FD;
+ height: 18px;
+ margin: 4px 3px 3px 3px;
+ position: absolute;
+ z-index: 10;
+ text-align: center;
+ -webkit-box-shadow: 0 0 1px rgba(0,0,0,0.25) inset;
+ -moz-box-shadow: 0 0 1px rgba(0,0,0,0.25) inset;
+ box-shadow: 0 0 1px rgba(0,0,0,0.25) inset;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.fn-gantt .bar .fn-label {
+ line-height: 18px;
+ font-weight: bold;
+ white-space: nowrap;
+ width: 100%;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ text-shadow: 0 1px 0 rgba(255,255,255,0.4);
+ color: #414B57 !important;
+ text-align: center;
+ font-size: 11px;
+}
+
+.fn-gantt .ganttRed {
+ background-color: #F9C4E1;
+}
+.fn-gantt .ganttRed .fn-label {
+ color: #78436D !important;
+}
+
+.fn-gantt .ganttGreen {
+ background-color: #D8EDA3;
+}
+.fn-gantt .ganttGreen .fn-label {
+ color: #778461 !important;
+}
+
+.fn-gantt .ganttOrange {
+ background-color: #FCD29A;
+}
+.fn-gantt .ganttOrange .fn-label {
+ color: #714715 !important;
+}
+
+
+/* === BOTTOM NAVIGATION === */
+
+.fn-gantt .bottom {
+ clear: both;
+ background-color: #f6f6f6;
+ width: 100%;
+}
+.fn-gantt .navigate {
+ border-top: 1px solid #DDD;
+ padding: 10px 0 10px 225px;
+}
+
+.fn-gantt .navigate .nav-slider {
+ height: 20px;
+ display: inline-block;
+}
+
+.fn-gantt .navigate .nav-slider-left, .fn-gantt .navigate .nav-slider-right {
+ text-align: center;
+ height: 20px;
+ display: inline-block;
+}
+
+.fn-gantt .navigate .nav-slider-left {
+ float: left;
+}
+
+.fn-gantt .navigate .nav-slider-right {
+ float: right;
+}
+
+.fn-gantt .navigate .nav-slider-content {
+ text-align: left;
+ width: 160px;
+ height: 20px;
+ display: inline-block;
+ margin: 0 10px;
+}
+
+.fn-gantt .navigate .nav-slider-bar, .fn-gantt .navigate .nav-slider-button {
+ position: absolute;
+ display: block;
+}
+
+.fn-gantt .navigate .nav-slider-bar {
+ width: 155px;
+ height: 6px;
+ background-color: #838688;
+ margin: 8px 0 0 0;
+ -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;
+ -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.fn-gantt .navigate .nav-slider-button {
+ width: 17px;
+ height: 60px;
+ background: url(../img/jquery.fn.gantt/slider_handle.png) center center no-repeat;
+ left: 0px;
+ top: 0px;
+ margin: -26px 0 0 0;
+ cursor: pointer;
+}
+
+.fn-gantt .navigate .page-number {
+ display: inline-block;
+ font-size: 10px;
+ height: 20px;
+}
+
+.fn-gantt .navigate .page-number span {
+ color: #666666;
+ margin: 0 6px;
+ height: 20px;
+ line-height: 20px;
+ display: inline-block;
+}
+
+.fn-gantt .navigate a:link, .fn-gantt .navigate a:visited, .fn-gantt .navigate a:active {
+ text-decoration: none;
+}
+
+.fn-gantt .nav-link {
+ margin: 0 3px 0 0;
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ font-size: 0px;
+ background: #595959 url(../img/jquery.fn.gantt/icon_sprite.png) !important;
+ border: 1px solid #454546;
+ cursor: pointer;
+ vertical-align: top;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ -webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2);
+ -moz-box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2);
+ box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 1px 1px rgba(0,0,0,0.2);
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.fn-gantt .nav-link:active {
+ -webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF;
+ -moz-box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF;
+ box-shadow: 0 1px 1px rgba(0,0,0,0.25) inset, 0 1px 0 #FFF;
+}
+
+.fn-gantt .navigate .nav-page-back {
+ background-position: 1px 0 !important;
+ margin: 0;
+}
+
+.fn-gantt .navigate .nav-page-next {
+ background-position: 1px -16px !important;
+ margin-right: 15px;
+}
+
+.fn-gantt .navigate .nav-slider .nav-page-next {
+ margin-right: 5px;
+}
+
+.fn-gantt .navigate .nav-begin {
+ background-position: 1px -112px !important;
+}
+
+.fn-gantt .navigate .nav-prev-week {
+ background-position: 1px -128px !important;
+}
+
+.fn-gantt .navigate .nav-prev-day {
+ background-position: 1px -48px !important;
+}
+
+.fn-gantt .navigate .nav-next-day {
+ background-position: 1px -64px !important;
+}
+
+.fn-gantt .navigate .nav-next-week {
+ background-position: 1px -160px !important;
+}
+
+.fn-gantt .navigate .nav-end {
+ background-position: 1px -144px !important;
+}
+
+.fn-gantt .navigate .nav-zoomOut {
+ background-position: 1px -96px !important;
+}
+
+.fn-gantt .navigate .nav-zoomIn {
+ background-position: 1px -80px !important;
+ margin-left: 15px;
+}
+
+.fn-gantt .navigate .nav-now {
+ background-position: 1px -32px !important;
+}
+
+.fn-gantt .navigate .nav-slider .nav-now {
+ margin-right: 5px;
+}
+
+.fn-gantt-loader {
+ background-image: url(../img/jquery.fn.gantt/loader_bg.png);
+ z-index: 30;
+}
+
+.fn-gantt-loader-spinner {
+ width: 100px;
+ height: 20px;
+ position: absolute;
+ margin-left: 50%;
+ margin-top: 50%;
+ text-align: center;
+}
+.fn-gantt-loader-spinner span {
+ color: #fff;
+ font-size: 12px;
+ font-weight: bold;
+}
+
+.row:after {
+ clear: both;
+}
+
Added: trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/grid.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/grid.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/icon_sprite.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/icon_sprite.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/loader_bg.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/loader_bg.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/slider_handle.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/img/jquery.fn.gantt/slider_handle.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Modified: trunk/chorem-webmotion/src/main/webapp/js/chorem.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/chorem.js 2013-06-25 09:55:33 UTC (rev 346)
+++ trunk/chorem-webmotion/src/main/webapp/js/chorem.js 2013-06-26 09:30:51 UTC (rev 347)
@@ -724,6 +724,7 @@
function displayFields() {
var id = $(this).attr('wikittyId');
+
if(this.selectedIndex == 0) {
$("#upgradeFields-" + id).text("");
}
@@ -732,25 +733,78 @@
$("#upgradeFields-" + id ).text("Loading fields for " + this.item(this.selectedIndex).label + "...");
var extensionName = this.item(this.selectedIndex).label;
+
$.get(createUrl("/project/json/getExtension/", extensionName, "/" + $(this).attr('wikittyId')),
function(data){
- //success
- var $jData = $(data);
-
+ //success
+ var $jData = $(data);
+
+
+ $("#upgradeFields-" + id).html($jData[0].outerHTML);//.innerHTML);
+ initFields();
- $("#upgradeFields-" + id).html($jData.html());//.innerHTML);
- initFields();
-
-
-
-
});
}
}
-$("a.upgrade").click(upgradeQuotation);
-$("select.extBox").change(displayFields);
-$("#project_hidden").change(function() {
- $("#projectSearch").submit();
-});
+ $("a.upgrade").click(upgradeQuotation);
+ $("select.extBox").change(displayFields);
+ $("#project_hidden").change(function() {
+ $("#projectSearch").submit();
+ });
+ function initgantt() {
+
+ var id = $(this).attr('wikittyId');
+
+
+ "use strict";
+
+
+
+ $(".gantt-"+id).gantt({
+ source: ganttData[id]['src'],
+ dateStart: ganttData[id]['startDate'],
+ dateEnd:ganttData[id]['endDate'],
+ extDate : {
+ "Draft sent" : ganttData[id]['sendingDate'],
+ "Sent" : ganttData[id]['postedDate'],
+ "Accepted" : ganttData[id]['acceptedDate'],
+ "Started" : ganttData[id]['startedDate'],
+ "Delivered" : ganttData[id]['deliveryDate'],
+ "RSV started" : ganttData[id]['rsvStart'],
+ "Warranty Started" : ganttData[id]['warrantyStart'],
+ "Closed" : ganttData[id]['closedDate'],
+ "Rejected" : ganttData[id]['rejectedDate'],
+ "Cancelled" : ganttData[id]['cancelledDate']
+ },
+ draftSent:ganttData[id]['draftSent'],
+ navigate: "scroll",
+ scale: "days",
+ maxScale: "months",
+ minScale: "days",
+ itemsPerPage: 10,
+ onItemClick: function(data) {
+ alert("Item clicked - show some details");
+ },
+ onAddClick: function(dt, rowId) {
+ alert("Empty space clicked - add an item!");
+ },
+ onRender: function() {
+ if (window.console && typeof console.log === "function") {
+ console.log("chart rendered");
+ }
+ }
+ });
+
+
+
+
+ prettyPrint();
+
+ }
+
+ $("a.ganttinit").click(initgantt);
+
+
+
});
\ No newline at end of file
Added: trunk/chorem-webmotion/src/main/webapp/js/jquery.fn.gantt.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jquery.fn.gantt.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jquery.fn.gantt.js 2013-06-26 09:30:51 UTC (rev 347)
@@ -0,0 +1,1807 @@
+// jQuery Gantt Chart
+// ==================
+
+// Basic usage:
+
+// $(".selector").gantt({
+// source: "ajax/data.json",
+// scale: "weeks",
+// minScale: "weeks",
+// maxScale: "months",
+// onItemClick: function(data) {
+// alert("Item clicked - show some details");
+// },
+// onAddClick: function(dt, rowId) {
+// alert("Empty space clicked - add an item!");
+// },
+// onRender: function() {
+// console.log("chart rendered");
+// }
+// });
+
+//
+/*jshint shadow:true, unused:false, laxbreak:true, evil:true*/
+/*globals jQuery, alert*/
+(function ($) {
+
+ "use strict";
+
+ $.fn.gantt = function (options) {
+
+ var cookieKey = "jquery.fn.gantt";
+ var scales = ["hours", "days", "weeks", "months"];
+ //Default settings
+ var settings = {
+ source: null,
+ itemsPerPage: 7,
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ dow: ["S", "M", "T", "W", "T", "F", "S"],
+ startPos: new Date(),
+ navigate: "buttons",
+ scale: "days",
+ useCookie: false,
+ maxScale: "months",
+ minScale: "hours",
+ waitText: "Please wait...",
+ onItemClick: function (data) { return; },
+ onAddClick: function (data) { return; },
+ onRender: function() { return; },
+ scrollToToday: true,
+ dateStart:null,
+ dateEnd: null,
+ extDate: null
+
+
+ };
+
+ // custom selector `:findday` used to match on specified day in ms.
+ //
+ // The selector is passed a date in ms and elements are added to the
+ // selection filter if the element date matches, as determined by the
+ // id attribute containing a parsable date in ms.
+ $.extend($.expr[":"], {
+ findday: function (a, i, m) {
+ var cd = new Date(parseInt(m[3], 10));
+ var id = $(a).attr("id");
+ id = id ? id : "";
+ var si = id.indexOf("-") + 1;
+ var ed = new Date(parseInt(id.substring(si, id.length), 10));
+ cd = new Date(cd.getFullYear(), cd.getMonth(), cd.getDate());
+ ed = new Date(ed.getFullYear(), ed.getMonth(), ed.getDate());
+ return cd.getTime() === ed.getTime();
+ }
+ });
+ // custom selector `:findweek` used to match on specified week in ms.
+ $.extend($.expr[":"], {
+ findweek: function (a, i, m) {
+ var cd = new Date(parseInt(m[3], 10));
+ var id = $(a).attr("id");
+ id = id ? id : "";
+ var si = id.indexOf("-") + 1;
+ cd = cd.getFullYear() + "-" + cd.getDayForWeek().getWeekOfYear();
+ var ed = id.substring(si, id.length);
+ return cd === ed;
+ }
+ });
+ // custom selector `:findmonth` used to match on specified month in ms.
+ $.extend($.expr[":"], {
+ findmonth: function (a, i, m) {
+ var cd = new Date(parseInt(m[3], 10));
+ cd = cd.getFullYear() + "-" + cd.getMonth();
+ var id = $(a).attr("id");
+ id = id ? id : "";
+ var si = id.indexOf("-") + 1;
+ var ed = id.substring(si, id.length);
+ return cd === ed;
+ }
+ });
+
+ // Date prototype helpers
+ // ======================
+
+ // `getWeekId` returns a string in the form of 'dh-YYYY-WW', where WW is
+ // the week # for the year.
+ // It is used to add an id to the week divs
+ Date.prototype.getWeekId = function () {
+ var y = this.getFullYear();
+ var w = this.getDayForWeek().getWeekOfYear();
+ var m = this.getMonth();
+ if (m === 11 && w === 1) {
+ y++;
+ }
+ return 'dh-' + y + "-" + w;
+ };
+
+ // `getRepDate` returns the seconds since the epoch for a given date
+ // depending on the active scale
+ Date.prototype.genRepDate = function () {
+ switch (settings.scale) {
+ case "hours":
+ return this.getTime();
+ case "weeks":
+ return this.getDayForWeek().getTime();
+ case "months":
+ return new Date(this.getFullYear(), this.getMonth(), 1).getTime();
+ default:
+ return this.getTime();
+ }
+ };
+
+ // `getDayOfYear` returns the day number for the year
+ Date.prototype.getDayOfYear = function () {
+ var fd = new Date(this.getFullYear(), 0, 0);
+ var sd = new Date(this.getFullYear(), this.getMonth(), this.getDate());
+ return Math.ceil((sd - fd) / 86400000);
+ };
+
+ // `getWeekOfYear` returns the week number for the year
+ Date.prototype.getWeekOfYear = function () {
+ var ys = new Date(this.getFullYear(), 0, 1);
+ var sd = new Date(this.getFullYear(), this.getMonth(), this.getDate());
+ if (ys.getDay() > 3) {
+ ys = new Date(sd.getFullYear(), 0, (7 - ys.getDay()));
+ }
+ var daysCount = sd.getDayOfYear() - ys.getDayOfYear();
+ return Math.ceil(daysCount / 7);
+
+ };
+
+ // `getDaysInMonth` returns the number of days in a month
+ Date.prototype.getDaysInMonth = function () {
+ return 32 - new Date(this.getFullYear(), this.getMonth(), 32).getDate();
+ };
+
+ // `hasWeek` returns `true` if the date resides on a week boundary
+ // **????????????????? Don't know if this is true**
+ Date.prototype.hasWeek = function () {
+ var df = new Date(this.valueOf());
+ df.setDate(df.getDate() - df.getDay());
+ var dt = new Date(this.valueOf());
+ dt.setDate(dt.getDate() + (6 - dt.getDay()));
+
+ if (df.getMonth() === dt.getMonth()) {
+ return true;
+ } else {
+ return (df.getMonth() === this.getMonth() && dt.getDate() < 4) || (df.getMonth() !== this.getMonth() && dt.getDate() >= 4);
+ }
+ };
+
+ // `getDayForWeek` returns the Date object for the starting date of
+ // the week # for the year
+ Date.prototype.getDayForWeek = function () {
+ var df = new Date(this.valueOf());
+ df.setDate(df.getDate() - df.getDay());
+ var dt = new Date(this.valueOf());
+ dt.setDate(dt.getDate() + (6 - dt.getDay()));
+ if ((df.getMonth() === dt.getMonth()) || (df.getMonth() !== dt.getMonth() && dt.getDate() >= 4)) {
+ return new Date(dt.setDate(dt.getDate() - 3));
+ } else {
+ return new Date(df.setDate(df.getDate() + 3));
+ }
+ };
+
+
+ // Grid management
+ // ===============
+
+ // Core object is responsible for navigation and rendering
+ var core = {
+ // Return the element whose topmost point lies under the given point
+ // Normalizes for IE
+ elementFromPoint: function (x, y) {
+
+ if ($.browser.msie) {
+ x -= $(document).scrollLeft();
+ y -= $(document).scrollTop();
+ } else {
+ x -= window.pageXOffset;
+ y -= window.pageYOffset;
+ }
+
+ return document.elementFromPoint(x, y);
+ },
+
+ // **Create the chart**
+ create: function (element) {
+
+ // Initialize data with a json object or fetch via an xhr
+ // request depending on `settings.source`
+ if (typeof settings.source !== "string") {
+ element.data = settings.source;
+ core.init(element);
+ } else {
+ $.getJSON(settings.source, function (jsData) {
+ element.data = jsData;
+ core.init(element);
+ });
+ }
+ },
+
+ // **Setup the initial view**
+ // Here we calculate the number of rows, pages and visible start
+ // and end dates once the data is ready
+ init: function (element) {
+ element.rowsNum = element.data.length;
+ element.pageCount = Math.ceil(element.rowsNum / settings.itemsPerPage);
+ element.rowsOnLastPage = element.rowsNum - (Math.floor(element.rowsNum / settings.itemsPerPage) * settings.itemsPerPage);
+
+ var settingsDateStart = tools.dateDeserialize(settings.dateStart);
+ var settingsDateEnd = tools.dateDeserialize(settings.dateEnd);
+
+ if(settingsDateStart == null || settingsDateStart>tools.getMinDate(element)) {
+ element.dateStart = tools.getMinDate(element);
+ }
+ else {
+ element.dateStart = settingsDateStart;
+ }
+ if(settingsDateEnd == null || settingsDateEnd<tools.getMaxDate(element)) {
+ element.dateEnd = tools.getMaxDate(element);
+ }
+ else {
+ element.dateEnd = settingsDateEnd;
+ }
+ console.log("date begin: " + element.dateStart);
+
+ /* core.render(element); */
+ core.waitToggle(element, true, function () { core.render(element); });
+ },
+
+ // **Render the grid**
+ render: function (element) {
+ var content = $('<div class="fn-content"/>');
+ var $leftPanel = core.leftPanel(element);
+ content.append($leftPanel);
+ var $rightPanel = core.rightPanel(element, $leftPanel);
+ var mLeft, hPos;
+
+ content.append($rightPanel);
+ content.append(core.navigation(element));
+
+ var $dataPanel = $rightPanel.find(".dataPanel");
+
+ element.gantt = $('<div class="fn-gantt" />').append(content);
+
+ $(element).html(element.gantt);
+
+ element.scrollNavigation.panelMargin = parseInt($dataPanel.css("margin-left").replace("px", ""), 10);
+ element.scrollNavigation.panelMaxPos = ($dataPanel.width() - $rightPanel.width());
+
+ element.scrollNavigation.canScroll = ($dataPanel.width() > $rightPanel.width());
+
+ core.markNow(element);
+ core.fillData(element, $dataPanel, $leftPanel);
+
+ // Set a cookie to record current position in the view
+ if (settings.useCookie) {
+ var sc = $.cookie(this.cookieKey + "ScrollPos");
+ if (sc) {
+ element.hPosition = sc;
+ }
+ }
+
+ //Apply mouseover
+ content.find('.begin').mouseover(core.mover).mouseout(core.mout).mousemove(core.mmove);
+ content.find('.end').mouseover(core.mover).mouseout(core.mout).mousemove(core.mmove);
+ content.find('.event').mouseover(core.mover).mouseout(core.mout).mousemove(core.mmove);
+
+
+ // Scroll the grid to today's date
+ if (settings.scrollToToday) {
+ var startPos = Math.round((settings.startPos / 1000 - element.dateStart / 1000) / 86400) - 2;
+ if ((startPos > 0 && element.hPosition !== 0)) {
+ if (element.scaleOldWidth) {
+ mLeft = ($dataPanel.width() - $rightPanel.width());
+ hPos = mLeft * element.hPosition / element.scaleOldWidth;
+ hPos = hPos > 0 ? 0 : hPos;
+ $dataPanel.css({ "margin-left": hPos + "px" });
+ element.scrollNavigation.panelMargin = hPos;
+ element.hPosition = hPos;
+ element.scaleOldWidth = null;
+ } else {
+ $dataPanel.css({ "margin-left": element.hPosition + "px" });
+ element.scrollNavigation.panelMargin = element.hPosition;
+ }
+ core.repositionLabel(element);
+ } else {
+ core.repositionLabel(element);
+ }
+ // or, scroll the grid to the left most date in the panel
+ } else {
+ if ((element.hPosition !== 0)) {
+ if (element.scaleOldWidth) {
+ mLeft = ($dataPanel.width() - $rightPanel.width());
+ hPos = mLeft * element.hPosition / element.scaleOldWidth;
+ hPos = hPos > 0 ? 0 : hPos;
+ $dataPanel.css({ "margin-left": hPos + "px" });
+ element.scrollNavigation.panelMargin = hPos;
+ element.hPosition = hPos;
+ element.scaleOldWidth = null;
+ } else {
+ $dataPanel.css({ "margin-left": element.hPosition + "px" });
+ element.scrollNavigation.panelMargin = element.hPosition;
+ }
+ core.repositionLabel(element);
+ } else {
+ core.repositionLabel(element);
+ }
+ }
+
+ $dataPanel.css({ height: $leftPanel.height() });
+ core.waitToggle(element, false);
+ settings.onRender();
+ },
+
+ mover : function (e) {
+ console.log("hint");
+ var hint;
+ if($(this).attr("over") == 'text')
+ hint = $('<div class="fn-gantt-hint"/>').html($(this).text());
+ else
+ hint = $('<div class="fn-gantt-hint"/>').html($(this).attr("over"));
+ $("body").append(hint);
+ hint.css("left", e.pageX);
+ hint.css("top", e.pageY);
+ hint.show();
+ },
+ mout : function () {
+ $(".fn-gantt-hint").remove();
+ },
+ mmove : function (e) {
+ $(".fn-gantt-hint").css("left", e.pageX);
+ $(".fn-gantt-hint").css("top", e.pageY + 15);
+ },
+
+
+
+
+ // Create and return the left panel with labels
+ leftPanel: function (element) {
+ /* Left panel */
+ var ganttLeftPanel = $('<div class="leftPanel"/>')
+ .append($('<div class="row spacer"/>')
+ .css("height", tools.getCellSize() * element.headerRows + "px")
+ .css("width", "100%"));
+
+ var entries = [];
+ $.each(element.data, function (i, entry) {
+ if (i >= element.pageNum * settings.itemsPerPage && i < (element.pageNum * settings.itemsPerPage + settings.itemsPerPage)) {
+
+ entries.push('<div class="row name row' + i + (entry.desc ? '' : ' fn-wide') + '" id="rowheader' + i + '" offset="' + i % settings.itemsPerPage * tools.getCellSize() + '">');
+ entries.push('<span class="fn-label' + (entry.cssClass ? ' ' + entry.cssClass : '') + '">' + entry.name + '</span>');
+ entries.push('</div>');
+
+ if (entry.desc) {
+ entries.push('<div class="row desc row' + i + ' " id="RowdId_' + i + '" data-id="' + entry.id + '">');
+
+ entries.push('<span class="fn-label' + (entry.cssClass ? ' ' + entry.cssClass : '') + '">' + entry.desc + '</span>');
+
+ entries.push('</div>');
+ }
+
+
+ }
+ });
+ ganttLeftPanel.append(entries.join(""));
+ ganttLeftPanel.find('.row:not(.spacer)').mouseover(core.mover)
+ .mouseout(core.mout)
+ .mousemove(core.mmove)
+ .attr('over', 'text');
+
+ return ganttLeftPanel;
+ },
+
+ // Create and return the data panel element
+ dataPanel: function (element, width) {
+ var dataPanel = $('<div class="dataPanel" style="width: ' + width + 'px;"/>');
+
+ // Handle mousewheel events for scrolling the data panel
+ var mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
+ if (document.attachEvent) {
+ element.attachEvent("on" + mousewheelevt, function (e) { core.wheelScroll(element, e); });
+ } else if (document.addEventListener) {
+ element.addEventListener(mousewheelevt, function (e) { core.wheelScroll(element, e); }, false);
+ }
+
+ // Handle click events and dispatch to registered `onAddClick`
+ // function
+ dataPanel.click(function (e) {
+
+ e.stopPropagation();
+ var corrX, corrY;
+ var leftpanel = $(element).find(".fn-gantt .leftPanel");
+ var datapanel = $(element).find(".fn-gantt .dataPanel");
+ switch (settings.scale) {
+ case "weeks":
+ corrY = tools.getCellSize() * 2;
+ break;
+ case "months":
+ corrY = tools.getCellSize();
+ break;
+ case "hours":
+ corrY = tools.getCellSize() * 4;
+ break;
+ case "days":
+ corrY = tools.getCellSize() * 3;
+ break;
+ default:
+ corrY = tools.getCellSize() * 2;
+ break;
+ }
+
+ /* Adjust, so get middle of elm
+ corrY -= Math.floor(tools.getCellSize() / 2);
+ */
+
+ // Find column where click occurred
+ var col = core.elementFromPoint(e.pageX, datapanel.offset().top + corrY);
+ // Was the label clicked directly?
+ if (col.className === "fn-label") {
+ col = $(col.parentNode);
+ } else {
+ col = $(col);
+ }
+
+ var dt = col.attr("repdate");
+ // Find row where click occurred
+ var row = core.elementFromPoint(leftpanel.offset().left + leftpanel.width() - 10, e.pageY);
+ // Was the lable clicked directly?
+ if (row.className.indexOf("fn-label") === 0) {
+ row = $(row.parentNode);
+ } else {
+ row = $(row);
+ }
+ var rowId = row.data().id;
+
+ // Dispatch user registered function with the DateTime in ms
+ // and the id if the clicked object is a row
+ settings.onAddClick(dt, rowId);
+ });
+ return dataPanel;
+ },
+
+ // Creates and return the right panel containing the year/week/day
+ // header
+ rightPanel: function (element, leftPanel) {
+
+ var range = null;
+ // Days of the week have a class of one of
+ // `sn` (Saturday), `sa` (Sunday), or `wd` (Weekday)
+ var dowClass = [" sn", " wd", " wd", " wd", " wd", " wd", " sa"];
+ var gridDowClass = [" sn", "", "", "", "", "", " sa"];
+
+ var yearArr = ['<div class="row"/>'];
+ var daysInYear = 0;
+
+ var monthArr = ['<div class="row"/>'];
+ var daysInMonth = 0;
+
+ var dayArr = [];
+
+ var hoursInDay = 0;
+
+ var dowArr = [];
+
+ var horArr = [];
+
+
+ var today = new Date();
+ today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
+ var holidays = settings.holidays ? settings.holidays.join() : '';
+
+ // Setup the headings based on the chosen `settings.scale`
+ switch (settings.scale) {
+ // **Hours**
+ case "hours":
+
+ range = tools.parseTimeRange(element.dateStart, element.dateEnd, element.scaleStep);
+
+ var year = range[0].getFullYear();
+ var month = range[0].getMonth();
+ var day = range[0];
+
+ for (var i = 0; i < range.length; i++) {
+ var rday = range[i];
+
+ // Fill years
+ var rfy = rday.getFullYear();
+ if (rfy !== year) {
+ yearArr.push(
+ ('<div class="row header year" style="width: '
+ + tools.getCellSize() * daysInYear
+ + 'px;"><div class="fn-label">'
+ + year
+ + '</div></div>'));
+
+ year = rfy;
+ daysInYear = 0;
+ }
+ daysInYear++;
+
+
+ // Fill months
+ var rm = rday.getMonth();
+ if (rm !== month) {
+ monthArr.push(
+ ('<div class="row header month" style="width: '
+ + tools.getCellSize() * daysInMonth + 'px"><div class="fn-label">'
+ + settings.months[month]
+ + '</div></div>'));
+
+ month = rm;
+ daysInMonth = 0;
+ }
+ daysInMonth++;
+
+
+ // Fill days & hours
+
+ var rgetDay = rday.getDay();
+ var getDay = day.getDay();
+ var day_class = dowClass[rgetDay];
+ var getTime = day.getTime();
+ if (holidays.indexOf((new Date(rday.getFullYear(), rday.getMonth(), rday.getDate())).getTime()) > -1) {
+ day_class = "holiday";
+ }
+ if (rgetDay !== getDay) {
+
+ var day_class2 = (today - day === 0) ? ' today' : (holidays.indexOf(getTime) > -1) ? "holiday" : dowClass[getDay];
+
+ dayArr.push('<div class="row date ' + day_class2 + '" '
+ + ' style="width: ' + tools.getCellSize() * hoursInDay + 'px;"> '
+ + ' <div class="fn-label">' + day.getDate() + '</div></div>');
+ dowArr.push('<div class="row day ' + day_class2 + '" '
+ + ' style="width: ' + tools.getCellSize() * hoursInDay + 'px;"> '
+ + ' <div class="fn-label">' + settings.dow[getDay] + '</div></div>');
+
+ day = rday;
+ hoursInDay = 0;
+ }
+ hoursInDay++;
+
+ horArr.push('<div class="row day '
+ + day_class
+ + '" id="dh-'
+ + rday.getTime()
+ + '" offset="' + i * tools.getCellSize() + '" repdate="' + rday.genRepDate() + '"> '
+ + rday.getHours()
+ + '</div>');
+ }
+
+
+ // Last year
+ yearArr.push(
+ '<div class="row header year" style="width: '
+ + tools.getCellSize() * daysInYear + 'px;"><div class="fn-label">'
+ + year
+ + '</div></div>');
+
+ // Last month
+ monthArr.push(
+ '<div class="row header month" style="width: '
+ + tools.getCellSize() * daysInMonth + 'px"><div class="fn-label">'
+ + settings.months[month]
+ + '</div></div>');
+
+ var day_class = dowClass[day.getDay()];
+
+ if (holidays.indexOf((new Date(day.getFullYear(), day.getMonth(), day.getDate())).getTime()) > -1) {
+ day_class = "holiday";
+ }
+
+ dayArr.push('<div class="row date ' + day_class + '" '
+ + ' style="width: ' + tools.getCellSize() * hoursInDay + 'px;"> '
+ + ' <div class="fn-label">' + day.getDate() + '</div></div>');
+
+ dowArr.push('<div class="row day ' + day_class + '" '
+ + ' style="width: ' + tools.getCellSize() * hoursInDay + 'px;"> '
+ + ' <div class="fn-label">' + settings.dow[day.getDay()] + '</div></div>');
+
+ var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());
+
+
+ // Append panel elements
+ dataPanel.append(yearArr.join(""));
+ dataPanel.append(monthArr.join(""));
+ dataPanel.append($('<div class="row"/>').html(dayArr.join("")));
+ dataPanel.append($('<div class="row"/>').html(dowArr.join("")));
+ dataPanel.append($('<div class="row"/>').html(horArr.join("")));
+
+ break;
+
+ // **Weeks**
+ case "weeks":
+ range = tools.parseWeeksRange(element.dateStart, element.dateEnd);
+ yearArr = ['<div class="row"/>'];
+ monthArr = ['<div class="row"/>'];
+ var year = range[0].getFullYear();
+ var month = range[0].getMonth();
+ var day = range[0];
+
+ for (var i = 0; i < range.length; i++) {
+ var rday = range[i];
+
+ // Fill years
+ if (rday.getFullYear() !== year) {
+ yearArr.push(
+ ('<div class="row header year" style="width: '
+ + tools.getCellSize() * daysInYear
+ + 'px;"><div class="fn-label">'
+ + year
+ + '</div></div>'));
+ year = rday.getFullYear();
+ daysInYear = 0;
+ }
+ daysInYear++;
+
+ // Fill months
+ if (rday.getMonth() !== month) {
+ monthArr.push(
+ ('<div class="row header month" style="width:'
+ + tools.getCellSize() * daysInMonth
+ + 'px;"><div class="fn-label">'
+ + settings.months[month]
+ + '</div></div>'));
+ month = rday.getMonth();
+ daysInMonth = 0;
+ }
+ daysInMonth++;
+
+ // Fill weeks
+ dayArr.push('<div class="row day wd" '
+ + ' id="' + rday.getWeekId() + '" offset="' + i * tools.getCellSize() + '" repdate="' + rday.genRepDate() + '"> '
+ + ' <div class="fn-label">' + rday.getWeekOfYear() + '</div></div>');
+ }
+
+
+ // Last year
+ yearArr.push(
+ '<div class="row header year" style="width: '
+ + tools.getCellSize() * daysInYear + 'px;"><div class="fn-label">'
+ + year
+ + '</div></div>');
+
+ // Last month
+ monthArr.push(
+ '<div class="row header month" style="width: '
+ + tools.getCellSize() * daysInMonth + 'px"><div class="fn-label">'
+ + settings.months[month]
+ + '</div></div>');
+
+ var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());
+
+ dataPanel.append(yearArr.join("") + monthArr.join("") + dayArr.join("") + (dowArr.join("")));
+
+ break;
+
+ // **Months**
+ case 'months':
+ range = tools.parseMonthsRange(element.dateStart, element.dateEnd);
+
+ var year = range[0].getFullYear();
+ var month = range[0].getMonth();
+ var day = range[0];
+
+ for (var i = 0; i < range.length; i++) {
+ var rday = range[i];
+
+ // Fill years
+ if (rday.getFullYear() !== year) {
+ yearArr.push(
+ ('<div class="row header year" style="width: '
+ + tools.getCellSize() * daysInYear
+ + 'px;"><div class="fn-label">'
+ + year
+ + '</div></div>'));
+ year = rday.getFullYear();
+ daysInYear = 0;
+ }
+ daysInYear++;
+ monthArr.push('<div class="row day wd" id="dh-' + tools.genId(rday.getTime()) + '" offset="' + i * tools.getCellSize() + '" repdate="' + rday.genRepDate() + '">' + (1 + rday.getMonth()) + '</div>');
+ }
+
+
+ // Last year
+ yearArr.push(
+ '<div class="row header year" style="width: '
+ + tools.getCellSize() * daysInYear + 'px;"><div class="fn-label">'
+ + year
+ + '</div></div>');
+
+ // Last month
+ monthArr.push(
+ '<div class="row header month" style="width: '
+ + tools.getCellSize() * daysInMonth + 'px">"<div class="fn-label">'
+ + settings.months[month]
+ + '</div></div>');
+
+ var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());
+
+ // Append panel elements
+ dataPanel.append(yearArr.join(""));
+ dataPanel.append(monthArr.join(""));
+ dataPanel.append($('<div class="row"/>').html(dayArr.join("")));
+ dataPanel.append($('<div class="row"/>').html(dowArr.join("")));
+
+ break;
+
+ // **Days (default)**
+ default:
+ range = tools.parseDateRange(element.dateStart, element.dateEnd);
+
+ var dateBefore = ktkGetNextDate(range[0], -1);
+ var year = dateBefore.getFullYear();
+ var month = dateBefore.getMonth();
+ var day = dateBefore;
+
+ dayArr.push('<div class="row date"></div>');
+ dowArr.push('<div class="row day"></div>')
+ for (var i = 0; i < range.length; i++) {
+ var rday = range[i];
+
+ // Fill years
+ if (rday.getFullYear() !== year) {
+ yearArr.push(
+ ('<div class="row header year" style="width:'
+ + tools.getCellSize() * daysInYear
+ + 'px;"><div class="fn-label">'
+ + year
+ + '</div></div>'));
+ year = rday.getFullYear();
+ daysInYear = 0;
+ }
+ daysInYear++;
+
+ // Fill months
+ if (rday.getMonth() !== month) {
+ monthArr.push(
+ ('<div class="row header month" style="width:'
+ + tools.getCellSize() * daysInMonth
+ + 'px;"><div class="fn-label">'
+ + settings.months[month]
+ + '</div></div>'));
+ month = rday.getMonth();
+ daysInMonth = 0;
+ }
+ daysInMonth++;
+
+ var getDay = rday.getDay();
+ var day_class = dowClass[getDay];
+ if (holidays.indexOf((new Date(rday.getFullYear(), rday.getMonth(), rday.getDate())).getTime()) > -1) {
+ day_class = "holiday";
+ }
+
+ dayArr.push('<div class="row date ' + day_class + '" '
+ + ' id="dh-' + tools.genId(rday.getTime()) + '" offset="' + i * tools.getCellSize() + '" repdate="' + rday.genRepDate() + '"> '
+ + ' <div class="fn-label">' + rday.getDate() + '</div></div>');
+ dowArr.push('<div class="row day ' + day_class + '" '
+ + ' id="dw-' + tools.genId(rday.getTime()) + '" repdate="' + rday.genRepDate() + '"> '
+ + ' <div class="fn-label">' + settings.dow[getDay] + '</div></div>');
+ } //for
+
+
+
+ // Last year
+ yearArr.push(
+ '<div class="row header year" style="width: '
+ + tools.getCellSize() * daysInYear + 'px;"><div class="fn-label">'
+ + year
+ + '</div></div>');
+
+ // Last month
+ monthArr.push(
+ '<div class="row header month" style="width: '
+ + tools.getCellSize() * daysInMonth + 'px"><div class="fn-label">'
+ + settings.months[month]
+ + '</div></div>');
+
+ var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());
+
+
+ // Append panel elements
+
+ dataPanel.append(yearArr.join(""));
+ dataPanel.append(monthArr.join(""));
+ dataPanel.append($('<div class="row"/>').html(dayArr.join("")));
+ dataPanel.append($('<div class="row"/>').html(dowArr.join("")));
+
+
+ break;
+ }
+ var ret = $('<div class="rightPanel"></div>').append(dataPanel);
+
+
+
+ return ret;
+ },
+
+ // **Navigation**
+ navigation: function (element) {
+ var ganttNavigate = null;
+ // Scrolling navigation is provided by setting
+ // `settings.navigate='scroll'`
+ if (settings.navigate === "scroll") {
+ ganttNavigate = $('<div class="navigate" />')
+ .append($('<div class="nav-slider" />')
+ .append($('<div class="nav-slider-left" />')
+ .append($('<span role="button" class="nav-link nav-page-back"/>')
+ .html('<')
+ .click(function () {
+ core.navigatePage(element, -1);
+ }))
+ .append($('<div class="page-number"/>')
+ .append($('<span/>')
+ .html(element.pageNum + 1 + ' of ' + element.pageCount)))
+ .append($('<span role="button" class="nav-link nav-page-next"/>')
+ .html('>')
+ .click(function () {
+ core.navigatePage(element, 1);
+ }))
+ .append($('<span role="button" class="nav-link nav-now"/>')
+ .html('●')
+ .click(function () {
+ core.navigateTo(element, 'now');
+ }))
+ .append($('<span role="button" class="nav-link nav-prev-week"/>')
+ .html('<<')
+ .click(function () {
+ if (settings.scale === 'hours') {
+ core.navigateTo(element, tools.getCellSize() * 8);
+ } else if (settings.scale === 'days') {
+ core.navigateTo(element, tools.getCellSize() * 30);
+ } else if (settings.scale === 'weeks') {
+ core.navigateTo(element, tools.getCellSize() * 12);
+ } else if (settings.scale === 'months') {
+ core.navigateTo(element, tools.getCellSize() * 6);
+ }
+ }))
+ .append($('<span role="button" class="nav-link nav-prev-day"/>')
+ .html('<')
+ .click(function () {
+ if (settings.scale === 'hours') {
+ core.navigateTo(element, tools.getCellSize() * 4);
+ } else if (settings.scale === 'days') {
+ core.navigateTo(element, tools.getCellSize() * 7);
+ } else if (settings.scale === 'weeks') {
+ core.navigateTo(element, tools.getCellSize() * 4);
+ } else if (settings.scale === 'months') {
+ core.navigateTo(element, tools.getCellSize() * 3);
+ }
+ })))
+ .append($('<div class="nav-slider-content" />')
+ .append($('<div class="nav-slider-bar" />')
+ .append($('<a class="nav-slider-button" />')
+ )
+ .mousedown(function (e) {
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ element.scrollNavigation.scrollerMouseDown = true;
+ core.sliderScroll(element, e);
+ })
+ .mousemove(function (e) {
+ if (element.scrollNavigation.scrollerMouseDown) {
+ core.sliderScroll(element, e);
+ }
+ })
+ )
+ )
+ .append($('<div class="nav-slider-right" />')
+ .append($('<span role="button" class="nav-link nav-next-day"/>')
+ .html('>')
+ .click(function () {
+ if (settings.scale === 'hours') {
+ core.navigateTo(element, tools.getCellSize() * -4);
+ } else if (settings.scale === 'days') {
+ core.navigateTo(element, tools.getCellSize() * -7);
+ } else if (settings.scale === 'weeks') {
+ core.navigateTo(element, tools.getCellSize() * -4);
+ } else if (settings.scale === 'months') {
+ core.navigateTo(element, tools.getCellSize() * -3);
+ }
+ }))
+ .append($('<span role="button" class="nav-link nav-next-week"/>')
+ .html('>>')
+ .click(function () {
+ if (settings.scale === 'hours') {
+ core.navigateTo(element, tools.getCellSize() * -8);
+ } else if (settings.scale === 'days') {
+ core.navigateTo(element, tools.getCellSize() * -30);
+ } else if (settings.scale === 'weeks') {
+ core.navigateTo(element, tools.getCellSize() * -12);
+ } else if (settings.scale === 'months') {
+ core.navigateTo(element, tools.getCellSize() * -6);
+ }
+ }))
+ .append($('<span role="button" class="nav-link nav-zoomIn"/>')
+ .html('+')
+ .click(function () {
+ core.zoomInOut(element, -1);
+ }))
+ .append($('<span role="button" class="nav-link nav-zoomOut"/>')
+ .html('-')
+ .click(function () {
+ core.zoomInOut(element, 1);
+ }))
+ )
+ );
+ $(document).mouseup(function () {
+ element.scrollNavigation.scrollerMouseDown = false;
+ });
+ // Button navigation is provided by setting `settings.navigation='buttons'`
+ } else {
+ ganttNavigate = $('<div class="navigate" />')
+ .append($('<span role="button" class="nav-link nav-page-back"/>')
+ .html('<')
+ .click(function () {
+ core.navigatePage(element, -1);
+ }))
+ .append($('<div class="page-number"/>')
+ .append($('<span/>')
+ .html(element.pageNum + 1 + ' of ' + element.pageCount)))
+ .append($('<span role="button" class="nav-link nav-page-next"/>')
+ .html('>')
+ .click(function () {
+ core.navigatePage(element, 1);
+ }))
+ .append($('<span role="button" class="nav-link nav-begin"/>')
+ .html('|<')
+ .click(function () {
+ core.navigateTo(element, 'begin');
+ }))
+ .append($('<span role="button" class="nav-link nav-prev-week"/>')
+ .html('<<')
+ .click(function () {
+ core.navigateTo(element, tools.getCellSize() * 7);
+ }))
+ .append($('<span role="button" class="nav-link nav-prev-day"/>')
+ .html('<')
+ .click(function () {
+ core.navigateTo(element, tools.getCellSize());
+ }))
+ .append($('<span role="button" class="nav-link nav-now"/>')
+ .html('●')
+ .click(function () {
+ core.navigateTo(element, 'now');
+ }))
+ .append($('<span role="button" class="nav-link nav-next-day"/>')
+ .html('>')
+ .click(function () {
+ core.navigateTo(element, tools.getCellSize() * -1);
+ }))
+ .append($('<span role="button" class="nav-link nav-next-week"/>')
+ .html('>>')
+ .click(function () {
+ core.navigateTo(element, tools.getCellSize() * -7);
+ }))
+ .append($('<span role="button" class="nav-link nav-end"/>')
+ .html('>|')
+ .click(function () {
+ core.navigateTo(element, 'end');
+ }))
+ .append($('<span role="button" class="nav-link nav-zoomIn"/>')
+ .html('+')
+ .click(function () {
+ core.zoomInOut(element, -1);
+ }))
+ .append($('<span role="button" class="nav-link nav-zoomOut"/>')
+ .html('-')
+ .click(function () {
+ core.zoomInOut(element, 1);
+ }));
+ }
+ return $('<div class="bottom"/>').append(ganttNavigate);
+ },
+
+ // **Progress Bar**
+ // Return an element representing a progress of position within
+ // the entire chart
+ createProgressBar: function (days, cls, desc, label, dataObj) {
+
+ var cellWidth = tools.getCellSize();
+ var barMarg = tools.getProgressBarMargin() || 0;
+ var bar = $('<div class="bar"><div class="fn-label">' + label + '</div></div>')
+ .addClass(cls)
+ .css({
+ width: ((cellWidth * days) - barMarg) + 5
+ })
+ .data("dataObj", dataObj);
+
+ //if (desc) {
+ bar.mouseover(core.mover)
+ .mouseout(core.mout)
+ .mousemove(core.mmove)
+ .attr('over', 'text');
+ //}
+ bar.click(function (e) {
+ e.stopPropagation();
+ settings.onItemClick($(this).data("dataObj"));
+ });
+ return bar;
+ },
+
+ // Remove the `wd` (weekday) class and add `today` class to the
+ // current day/week/month (depending on the current scale)
+ markNow: function (element) {
+ switch (settings.scale) {
+ case "weeks":
+ var cd = Date.parse(new Date());
+ cd = (Math.floor(cd / 36400000) * 36400000);
+ $(element).find(':findweek("' + cd + '")').removeClass('wd').addClass('today');
+ break;
+ case "months":
+ $(element).find(':findmonth("' + new Date().getTime() + '")').removeClass('wd').addClass('today');
+ break;
+ default:
+ var cd = Date.parse(new Date());
+ cd = (Math.floor(cd / 36400000) * 36400000);
+ $(element).find(':findday("' + cd + '")').removeClass('wd').addClass('today');
+ var bd = Date.parse(tools.dateDeserialize(settings.dateStart));
+ //bd = (Math.floor(bd / 36400000) * 36400000);
+ $(element).find(':findday("' + bd + '")').removeClass('wd').addClass('begin').attr('over',"Project start");
+
+ $(element).find(':findday("' + Date.parse(tools.dateDeserialize(settings.dateEnd)) + '")').removeClass('wd').addClass('end').attr('over',"Project end");
+ console.log(settings.extDate);
+ for(var key in settings.extDate) {
+ console.log("passe");
+ if(settings.extDate[key] != undefined)
+ $(element).find(':findday("' + Date.parse(tools.dateDeserialize(settings.extDate[key])) + '")').removeClass('wd').addClass('event').attr('over',key);
+ }
+ break;
+ }
+ },
+
+ // **Fill the Chart**
+ // Parse the data and fill the data panel
+ fillData: function (element, datapanel, leftpanel) {
+ var invertColor = function (colStr) {
+ try {
+ colStr = colStr.replace("rgb(", "").replace(")", "");
+ var rgbArr = colStr.split(",");
+ var R = parseInt(rgbArr[0], 10);
+ var G = parseInt(rgbArr[1], 10);
+ var B = parseInt(rgbArr[2], 10);
+ var gray = Math.round((255 - (0.299 * R + 0.587 * G + 0.114 * B)) * 0.9, 1);
+ return "rgb(" + gray + ", " + gray + ", " + gray + ")";
+ } catch (err) {
+ return "";
+ }
+ };
+ // Loop through the values of each data element and set a row
+ $.each(element.data, function (i, entry) {
+ if (i >= element.pageNum * settings.itemsPerPage && i < (element.pageNum * settings.itemsPerPage + settings.itemsPerPage)) {
+
+ $.each(entry.values, function (j, day) {
+ var _bar = null;
+
+
+ switch (settings.scale) {
+ // **Hourly data**
+ case "hours":
+ var dFrom = tools.genId(tools.dateDeserialize(day.from).getTime(), element.scaleStep);
+ var from = $(element).find('#dh-' + dFrom);
+
+ var dTo = tools.genId(tools.dateDeserialize(day.to).getTime(), element.scaleStep);
+ var to = $(element).find('#dh-' + dTo);
+
+ var cFrom = from.attr("offset");
+ var cTo = to.attr("offset");
+ var dl = Math.floor((cTo - cFrom) / tools.getCellSize()) + 1;
+
+ _bar = core.createProgressBar(
+ dl,
+ day.customClass ? day.customClass : "",
+ entry.desc ? entry.desc : "",
+ day.label ? day.label : "",
+ day.dataObj ? day.dataObj : null
+ );
+
+ // find row
+ var topEl = $(element).find("#rowheader" + i);
+
+ var top = tools.getCellSize() * 5 + 2 + parseInt(topEl.attr("offset"), 10);
+ _bar.css({ 'margin-top': top, 'margin-left': Math.floor(cFrom) });
+
+ datapanel.append(_bar);
+ break;
+
+ // **Weekly data**
+ case "weeks":
+ var dtFrom = tools.dateDeserialize(day.from);
+ var dtTo = tools.dateDeserialize(day.to);
+
+ if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
+ dtFrom.setDate(dtFrom.getDate() + 4);
+ }
+
+ if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
+ dtFrom.setDate(dtFrom.getDate() + 4);
+ }
+
+ if (dtTo.getDate() <= 3 && dtTo.getMonth() === 0) {
+ dtTo.setDate(dtTo.getDate() + 4);
+ }
+
+ var from = $(element).find("#" + dtFrom.getWeekId());
+
+ var cFrom = from.attr("offset");
+
+ var to = $(element).find("#" + dtTo.getWeekId());
+ var cTo = to.attr("offset");
+
+ var dl = Math.round((cTo - cFrom) / tools.getCellSize()) + 1;
+
+ _bar = core.createProgressBar(
+ dl,
+ day.customClass ? day.customClass : "",
+ entry.desc ? entry.desc : "",
+ day.label ? day.label : "",
+ day.dataObj ? day.dataObj : null
+ );
+
+ // find row
+ var topEl = $(element).find("#rowheader" + i);
+
+ var top = tools.getCellSize() * 3 + 2 + parseInt(topEl.attr("offset"), 10);
+ _bar.css({ 'margin-top': top, 'margin-left': Math.floor(cFrom) });
+
+ datapanel.append(_bar);
+ break;
+
+ // **Monthly data**
+ case "months":
+ var dtFrom = tools.dateDeserialize(day.from);
+ var dtTo = tools.dateDeserialize(day.to);
+
+ if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
+ dtFrom.setDate(dtFrom.getDate() + 4);
+ }
+
+ if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
+ dtFrom.setDate(dtFrom.getDate() + 4);
+ }
+
+ if (dtTo.getDate() <= 3 && dtTo.getMonth() === 0) {
+ dtTo.setDate(dtTo.getDate() + 4);
+ }
+
+ var from = $(element).find("#dh-" + tools.genId(dtFrom.getTime()));
+ var cFrom = from.attr("offset");
+ var to = $(element).find("#dh-" + tools.genId(dtTo.getTime()));
+ var cTo = to.attr("offset");
+ var dl = Math.round((cTo - cFrom) / tools.getCellSize()) + 1;
+
+ _bar = core.createProgressBar(
+ dl,
+ day.customClass ? day.customClass : "",
+ entry.desc ? entry.desc : "",
+ day.label ? day.label : "",
+ day.dataObj ? day.dataObj : null
+ );
+
+ // find row
+ var topEl = $(element).find("#rowheader" + i);
+
+ var top = tools.getCellSize() * 2 + 2 + parseInt(topEl.attr("offset"), 10);
+ _bar.css({ 'margin-top': top, 'margin-left': Math.floor(cFrom) });
+
+ datapanel.append(_bar);
+ break;
+
+ // **Days**
+ default:
+ var dFrom = tools.genId(tools.dateDeserialize(day.from).getTime());
+ var dTo = tools.genId(tools.dateDeserialize(day.to).getTime());
+
+ var from = $(element).find("#dh-" + dFrom);
+ var cFrom = from.attr("offset");
+
+ var dl = Math.floor(((dTo / 1000) - (dFrom / 1000)) / 86400) + 1;
+ _bar = core.createProgressBar(
+ dl,
+ day.customClass ? day.customClass : "",
+ entry.desc ? entry.desc : "",
+ day.label ? day.label : "",
+ day.dataObj ? day.dataObj : null
+ );
+
+ // find row
+ var topEl = $(element).find("#rowheader" + i);
+
+ var top = tools.getCellSize() * 4 + 2 + parseInt(topEl.attr("offset"), 10);
+ _bar.css({ 'margin-top': top, 'margin-left': Math.floor(cFrom) });
+
+ datapanel.append(_bar);
+
+ break;
+ }
+ var $l = _bar.find(".fn-label");
+ if ($l && _bar.length) {
+ var gray = invertColor(_bar[0].style.backgroundColor);
+ $l.css("color", gray);
+ } else if ($l) {
+ $l.css("color", "");
+ }
+ });
+
+ }
+ });
+ },
+ // **Navigation**
+ navigateTo: function (element, val) {
+ var $rightPanel = $(element).find(".fn-gantt .rightPanel");
+ var $dataPanel = $rightPanel.find(".dataPanel");
+ $dataPanel.click = function () {
+ alert(arguments.join(""));
+ };
+ var rightPanelWidth = $rightPanel.width();
+ var dataPanelWidth = $dataPanel.width();
+
+ switch (val) {
+ case "begin":
+ $dataPanel.animate({
+ "margin-left": "0px"
+ }, "fast", function () { core.repositionLabel(element); });
+ element.scrollNavigation.panelMargin = 0;
+ break;
+ case "end":
+ var mLeft = dataPanelWidth - rightPanelWidth;
+ element.scrollNavigation.panelMargin = mLeft * -1;
+ $dataPanel.animate({
+ "margin-left": "-" + mLeft + "px"
+ }, "fast", function () { core.repositionLabel(element); });
+ break;
+ case "now":
+ if (!element.scrollNavigation.canScroll || !$dataPanel.find(".today").length) {
+ return false;
+ }
+ var max_left = (dataPanelWidth - rightPanelWidth) * -1;
+ var cur_marg = $dataPanel.css("margin-left").replace("px", "");
+ var val = $dataPanel.find(".today").offset().left - $dataPanel.offset().left;
+ val *= -1;
+ if (val > 0) {
+ val = 0;
+ } else if (val < max_left) {
+ val = max_left;
+ }
+ $dataPanel.animate({
+ "margin-left": val + "px"
+ }, "fast", core.repositionLabel(element));
+ element.scrollNavigation.panelMargin = val;
+ break;
+ default:
+ var max_left = (dataPanelWidth - rightPanelWidth) * -1;
+ var cur_marg = $dataPanel.css("margin-left").replace("px", "");
+ var val = parseInt(cur_marg, 10) + val;
+ if (val <= 0 && val >= max_left) {
+ $dataPanel.animate({
+ "margin-left": val + "px"
+ }, "fast", core.repositionLabel(element));
+ }
+ element.scrollNavigation.panelMargin = val;
+ break;
+ }
+ },
+
+ // Navigate to a specific page
+ navigatePage: function (element, val) {
+ if ((element.pageNum + val) >= 0 && (element.pageNum + val) < Math.ceil(element.rowsNum / settings.itemsPerPage)) {
+ core.waitToggle(element, true, function () {
+ element.pageNum += val;
+ element.hPosition = $(".fn-gantt .dataPanel").css("margin-left").replace("px", "");
+ element.scaleOldWidth = false;
+ core.init(element);
+ });
+ }
+ },
+
+ // Change zoom level
+ zoomInOut: function (element, val) {
+ core.waitToggle(element, true, function () {
+
+ var zoomIn = (val < 0);
+
+ var scaleSt = element.scaleStep + val * 3;
+ scaleSt = scaleSt <= 1 ? 1 : scaleSt === 4 ? 3 : scaleSt;
+ var scale = settings.scale;
+ var headerRows = element.headerRows;
+ if (settings.scale === "hours" && scaleSt >= 13) {
+ scale = "days";
+ headerRows = 4;
+ scaleSt = 13;
+ } else if (settings.scale === "days" && zoomIn) {
+ scale = "hours";
+ headerRows = 5;
+ scaleSt = 12;
+ } else if (settings.scale === "days" && !zoomIn) {
+ scale = "weeks";
+ headerRows = 3;
+ scaleSt = 13;
+ } else if (settings.scale === "weeks" && !zoomIn) {
+ scale = "months";
+ headerRows = 2;
+ scaleSt = 14;
+ } else if (settings.scale === "weeks" && zoomIn) {
+ scale = "days";
+ headerRows = 4;
+ scaleSt = 13;
+ } else if (settings.scale === "months" && zoomIn) {
+ scale = "weeks";
+ headerRows = 3;
+ scaleSt = 13;
+ }
+
+ if ((zoomIn && $.inArray(scale, scales) < $.inArray(settings.minScale, scales))
+ || (!zoomIn && $.inArray(scale, scales) > $.inArray(settings.maxScale, scales))) {
+ core.init(element);
+ return;
+ }
+ element.scaleStep = scaleSt;
+ settings.scale = scale;
+ element.headerRows = headerRows;
+ var $rightPanel = $(element).find(".fn-gantt .rightPanel");
+ var $dataPanel = $rightPanel.find(".dataPanel");
+ element.hPosition = $dataPanel.css("margin-left").replace("px", "");
+ element.scaleOldWidth = ($dataPanel.width() - $rightPanel.width());
+
+ if (settings.useCookie) {
+ $.cookie(this.cookieKey + "CurrentScale", settings.scale);
+ // reset scrollPos
+ $.cookie(this.cookieKey + "ScrollPos", null);
+ }
+ core.init(element);
+ });
+ },
+
+ // Move chart via mouseclick
+ mouseScroll: function (element, e) {
+ var $dataPanel = $(element).find(".fn-gantt .dataPanel");
+ $dataPanel.css("cursor", "move");
+ var bPos = $dataPanel.offset();
+ var mPos = element.scrollNavigation.mouseX === null ? e.pageX : element.scrollNavigation.mouseX;
+ var delta = e.pageX - mPos;
+ element.scrollNavigation.mouseX = e.pageX;
+
+ core.scrollPanel(element, delta);
+
+ clearTimeout(element.scrollNavigation.repositionDelay);
+ element.scrollNavigation.repositionDelay = setTimeout(core.repositionLabel, 50, element);
+ },
+
+ // Move chart via mousewheel
+ wheelScroll: function (element, e) {
+ var delta = e.detail ? e.detail * (-50) : e.wheelDelta / 120 * 50;
+
+ core.scrollPanel(element, delta);
+
+ clearTimeout(element.scrollNavigation.repositionDelay);
+ element.scrollNavigation.repositionDelay = setTimeout(core.repositionLabel, 50, element);
+
+ if (e.preventDefault) {
+ e.preventDefault();
+ } else {
+ return false;
+ }
+ },
+
+ // Move chart via slider control
+ sliderScroll: function (element, e) {
+ var $sliderBar = $(element).find(".nav-slider-bar");
+ var $sliderBarBtn = $sliderBar.find(".nav-slider-button");
+ var $rightPanel = $(element).find(".fn-gantt .rightPanel");
+ var $dataPanel = $rightPanel.find(".dataPanel");
+
+ var bPos = $sliderBar.offset();
+ var bWidth = $sliderBar.width();
+ var wButton = $sliderBarBtn.width();
+
+ var pos, mLeft;
+
+ if ((e.pageX >= bPos.left) && (e.pageX <= bPos.left + bWidth)) {
+ pos = e.pageX - bPos.left;
+ pos = pos - wButton / 2;
+ $sliderBarBtn.css("left", pos);
+
+ mLeft = $dataPanel.width() - $rightPanel.width();
+
+ var pPos = pos * mLeft / bWidth * -1;
+ if (pPos >= 0) {
+ $dataPanel.css("margin-left", "0px");
+ element.scrollNavigation.panelMargin = 0;
+ } else if (pos >= bWidth - (wButton * 1)) {
+ $dataPanel.css("margin-left", mLeft * -1 + "px");
+ element.scrollNavigation.panelMargin = mLeft * -1;
+ } else {
+ $dataPanel.css("margin-left", pPos + "px");
+ element.scrollNavigation.panelMargin = pPos;
+ }
+ clearTimeout(element.scrollNavigation.repositionDelay);
+ element.scrollNavigation.repositionDelay = setTimeout(core.repositionLabel, 5, element);
+ }
+ },
+
+ // Update scroll panel margins
+ scrollPanel: function (element, delta) {
+ if (!element.scrollNavigation.canScroll) {
+ return false;
+ }
+ var _panelMargin = parseInt(element.scrollNavigation.panelMargin, 10) + delta;
+ if (_panelMargin > 0) {
+ element.scrollNavigation.panelMargin = 0;
+ $(element).find(".fn-gantt .dataPanel").css("margin-left", element.scrollNavigation.panelMargin + "px");
+ } else if (_panelMargin < element.scrollNavigation.panelMaxPos * -1) {
+ element.scrollNavigation.panelMargin = element.scrollNavigation.panelMaxPos * -1;
+ $(element).find(".fn-gantt .dataPanel").css("margin-left", element.scrollNavigation.panelMargin + "px");
+ } else {
+ element.scrollNavigation.panelMargin = _panelMargin;
+ $(element).find(".fn-gantt .dataPanel").css("margin-left", element.scrollNavigation.panelMargin + "px");
+ }
+ core.synchronizeScroller(element);
+ },
+
+ // Synchronize scroller
+ synchronizeScroller: function (element) {
+ if (settings.navigate === "scroll") {
+ var $rightPanel = $(element).find(".fn-gantt .rightPanel");
+ var $dataPanel = $rightPanel.find(".dataPanel");
+ var $sliderBar = $(element).find(".nav-slider-bar");
+ var $sliderBtn = $sliderBar.find(".nav-slider-button");
+
+ var bWidth = $sliderBar.width();
+ var wButton = $sliderBtn.width();
+
+ var mLeft = $dataPanel.width() - $rightPanel.width();
+ var hPos = 0;
+ if ($dataPanel.css("margin-left")) {
+ hPos = $dataPanel.css("margin-left").replace("px", "");
+ }
+ var pos = hPos * bWidth / mLeft - $sliderBtn.width() * 0.25;
+ pos = pos > 0 ? 0 : (pos * -1 >= bWidth - (wButton * 0.75)) ? (bWidth - (wButton * 1.25)) * -1 : pos;
+ $sliderBtn.css("left", pos * -1);
+ }
+ },
+
+ // Reposition data labels
+ repositionLabel: function (element) {
+ setTimeout(function () {
+ var $dataPanel;
+ if (!element) {
+ $dataPanel = $(".fn-gantt .rightPanel .dataPanel");
+ } else {
+ var $rightPanel = $(element).find(".fn-gantt .rightPanel");
+ $dataPanel = $rightPanel.find(".dataPanel");
+ }
+
+ if (settings.useCookie) {
+ $.cookie(this.cookieKey + "ScrollPos", $dataPanel.css("margin-left").replace("px", ""));
+ }
+ }, 500);
+ },
+
+ // waitToggle
+ waitToggle: function (element, show, fn) {
+ if (show) {
+ var eo = $(element).offset();
+ var ew = $(element).outerWidth();
+ var eh = $(element).outerHeight();
+
+ if (!element.loader) {
+ element.loader = $('<div class="fn-gantt-loader" style="position: absolute; top: ' + eo.top + 'px; left: ' + eo.left + 'px; width: ' + ew + 'px; height: ' + eh + 'px;">'
+ + '<div class="fn-gantt-loader-spinner"><span>' + settings.waitText + '</span></div></div>');
+ }
+ $("body").append(element.loader);
+ setTimeout(fn, 100);
+
+ } else {
+ if (element.loader) {
+ element.loader.remove();
+ }
+ element.loader = null;
+ }
+ }
+ };
+
+ // Utility functions
+ // =================
+ var tools = {
+
+ // Return the maximum available date in data depending on the scale
+ getMaxDate: function (element) {
+ var maxDate = null;
+
+ $.each(element.data, function (i, entry) {
+ $.each(entry.values, function (i, date) {
+ maxDate = maxDate < tools.dateDeserialize(date.to) ? tools.dateDeserialize(date.to) : maxDate;
+ });
+ });
+
+ switch (settings.scale) {
+ case "hours":
+ maxDate.setHours(Math.ceil((maxDate.getHours()) / element.scaleStep) * element.scaleStep);
+ maxDate.setHours(maxDate.getHours() + element.scaleStep * 3);
+ break;
+ case "weeks":
+ var bd = new Date(maxDate.getTime());
+ var bd = new Date(bd.setDate(bd.getDate() + 3 * 7));
+ var md = Math.floor(bd.getDate() / 7) * 7;
+ maxDate = new Date(bd.getFullYear(), bd.getMonth(), md === 0 ? 4 : md - 3);
+ break;
+ case "months":
+ var bd = new Date(maxDate.getFullYear(), maxDate.getMonth(), 1);
+ bd.setMonth(bd.getMonth() + 2);
+ maxDate = new Date(bd.getFullYear(), bd.getMonth(), 1);
+ break;
+ default:
+ maxDate.setHours(0);
+ maxDate.setDate(maxDate.getDate() + 3);
+ break;
+ }
+ return maxDate;
+ },
+
+ // Return the minimum available date in data depending on the scale
+ getMinDate: function (element) {
+ var minDate = null;
+
+ $.each(element.data, function (i, entry) {
+ $.each(entry.values, function (i, date) {
+ minDate = minDate > tools.dateDeserialize(date.from) || minDate === null ? tools.dateDeserialize(date.from) : minDate;
+ });
+ });
+ switch (settings.scale) {
+ case "hours":
+ minDate.setHours(Math.floor((minDate.getHours()) / element.scaleStep) * element.scaleStep);
+ minDate.setHours(minDate.getHours() - element.scaleStep * 3);
+ break;
+ case "weeks":
+ var bd = new Date(minDate.getTime());
+ var bd = new Date(bd.setDate(bd.getDate() - 3 * 7));
+ var md = Math.floor(bd.getDate() / 7) * 7;
+ minDate = new Date(bd.getFullYear(), bd.getMonth(), md === 0 ? 4 : md - 3);
+ break;
+ case "months":
+ var bd = new Date(minDate.getFullYear(), minDate.getMonth(), 1);
+ bd.setMonth(bd.getMonth() - 3);
+ minDate = new Date(bd.getFullYear(), bd.getMonth(), 1);
+ break;
+ default:
+ minDate.setHours(0);
+ minDate.setDate(minDate.getDate() - 3);
+ break;
+ }
+ return minDate;
+ },
+
+ // Return an array of Date objects between `from` and `to`
+ parseDateRange: function (from, to) {
+ var current = new Date(from.getTime());
+ var end = new Date(to.getTime());
+ var ret = [];
+ var i = 0;
+ do {
+ ret[i++] = new Date(current.getTime());
+ current.setDate(current.getDate() + 1);
+ } while (current.getTime() <= to.getTime());
+ return ret;
+
+ },
+
+ // Return an array of Date objects between `from` and `to`,
+ // scaled hourly
+ parseTimeRange: function (from, to, scaleStep) {
+ var current = new Date(from);
+ var end = new Date(to);
+ var ret = [];
+ var i = 0;
+ for(;;) {
+ var dayStartTime = new Date(current);
+ dayStartTime.setHours(Math.floor((current.getHours()) / scaleStep) * scaleStep);
+
+ if (ret[i] && dayStartTime.getDay() !== ret[i].getDay()) {
+ // If mark-cursor jumped to next day, make sure it starts at 0 hours
+ dayStartTime.setHours(0);
+ }
+ ret[i] = dayStartTime;
+
+ // Note that we use ">" because we want to include the end-time point.
+ if(current.getTime() > to.getTime()) break;
+
+ /* BUG-2: current is moved backwards producing a dead-lock! (crashes chrome/IE/firefox)
+ * SEE: https://github.com/taitems/jQuery.Gantt/issues/62
+ if (current.getDay() !== ret[i].getDay()) {
+ current.setHours(0);
+ }
+ */
+
+ current = ktkGetNextDate(current, scaleStep);
+
+ i++;
+ };
+
+ return ret;
+ },
+
+ // Return an array of Date objects between a range of weeks
+ // between `from` and `to`
+ parseWeeksRange: function (from, to) {
+
+ var current = new Date(from);
+ var end = new Date(to);
+
+ var ret = [];
+ var i = 0;
+ do {
+ if (current.getDay() === 0) {
+ ret[i++] = current.getDayForWeek();
+ }
+ current.setDate(current.getDate() + 1);
+ } while (current.getTime() <= to.getTime());
+
+ return ret;
+ },
+
+
+ // Return an array of Date objects between a range of months
+ // between `from` and `to`
+ parseMonthsRange: function (from, to) {
+
+ var current = new Date(from);
+ var end = new Date(to);
+
+ var ret = [];
+ var i = 0;
+ do {
+ ret[i++] = new Date(current.getFullYear(), current.getMonth(), 1);
+ current.setMonth(current.getMonth() + 1);
+ } while (current.getTime() <= to.getTime());
+
+ return ret;
+ },
+
+ // Deserialize a date from a string
+ dateDeserialize: function (dateStr) {
+
+ return eval("new" + dateStr.replace(/\//g, " "));
+ //var date = eval("new" + dateStr.replace(/\//g, " "));
+ //return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes());
+ },
+
+ // Generate an id for a date
+ genId: function (ticks) {
+ var t = new Date(ticks);
+ switch (settings.scale) {
+ case "hours":
+ var hour = t.getHours();
+ if (arguments.length >= 2) {
+ hour = (Math.floor((t.getHours()) / arguments[1]) * arguments[1]);
+ }
+ return (new Date(t.getFullYear(), t.getMonth(), t.getDate(), hour)).getTime();
+ case "weeks":
+ var y = t.getFullYear();
+ var w = t.getDayForWeek().getWeekOfYear();
+ var m = t.getMonth();
+ if (m === 11 && w === 1) {
+ y++;
+ }
+ return y + "-" + w;
+ case "months":
+ return t.getFullYear() + "-" + t.getMonth();
+ default:
+ return (new Date(t.getFullYear(), t.getMonth(), t.getDate())).getTime();
+ }
+ },
+
+ // Get the current cell size
+ _getCellSize: null,
+ getCellSize: function () {
+ if (!tools._getCellSize) {
+ $("body").append(
+ $('<div style="display: none; position: absolute;" class="fn-gantt" id="measureCellWidth"><div class="row"></div></div>')
+ );
+ tools._getCellSize = $("#measureCellWidth .row").height();
+ $("#measureCellWidth").empty().remove();
+ }
+ return tools._getCellSize;
+ },
+
+ // Get the current size of the rigth panel
+ getRightPanelSize: function () {
+ $("body").append(
+ $('<div style="display: none; position: absolute;" class="fn-gantt" id="measureCellWidth"><div class="rightPanel"></div></div>')
+ );
+ var ret = $("#measureCellWidth .rightPanel").height();
+ $("#measureCellWidth").empty().remove();
+ return ret;
+ },
+
+ // Get the current page height
+ getPageHeight: function (element) {
+ return element.pageNum + 1 === element.pageCount ? element.rowsOnLastPage * tools.getCellSize() : settings.itemsPerPage * tools.getCellSize();
+ },
+
+ // Get the current margin size of the progress bar
+ _getProgressBarMargin: null,
+ getProgressBarMargin: function () {
+ if (!tools._getProgressBarMargin) {
+ $("body").append(
+ $('<div style="display: none; position: absolute;" id="measureBarWidth" ><div class="fn-gantt"><div class="rightPanel"><div class="dataPanel"><div class="row day"><div class="bar" /></div></div></div></div></div>')
+ );
+ tools._getProgressBarMargin = parseInt($("#measureBarWidth .fn-gantt .rightPanel .day .bar").css("margin-left").replace("px", ""), 10);
+ tools._getProgressBarMargin += parseInt($("#measureBarWidth .fn-gantt .rightPanel .day .bar").css("margin-right").replace("px", ""), 10);
+ $("#measureBarWidth").empty().remove();
+ }
+ return tools._getProgressBarMargin;
+ }
+ };
+
+
+ this.each(function () {
+ /**
+ * Extend options with default values
+ */
+ if (options) {
+ $.extend(settings, options);
+ }
+
+ this.data = null; // Received data
+ this.pageNum = 0; // Current page number
+ this.pageCount = 0; // Available pages count
+ this.rowsOnLastPage = 0; // How many rows on last page
+ this.rowsNum = 0; // Number of total rows
+ this.hPosition = 0; // Current position on diagram (Horizontal)
+ this.dateStart = null;
+ this.dateEnd = null;
+ this.scrollClicked = false;
+ this.scaleOldWidth = null;
+ this.headerRows = null;
+
+ // Update cookie with current scale
+ if (settings.useCookie) {
+ var sc = $.cookie(this.cookieKey + "CurrentScale");
+ if (sc) {
+ settings.scale = $.cookie(this.cookieKey + "CurrentScale");
+ } else {
+ $.cookie(this.cookieKey + "CurrentScale", settings.scale);
+ }
+ }
+
+ switch (settings.scale) {
+ //case "hours": this.headerRows = 5; this.scaleStep = 8; break;
+ case "hours": this.headerRows = 5; this.scaleStep = 1; break;
+ case "weeks": this.headerRows = 3; this.scaleStep = 13; break;
+ case "months": this.headerRows = 2; this.scaleStep = 14; break;
+ default: this.headerRows = 4; this.scaleStep = 13; break;
+ }
+
+ this.scrollNavigation = {
+ panelMouseDown: false,
+ scrollerMouseDown: false,
+ mouseX: null,
+ panelMargin: 0,
+ repositionDelay: 0,
+ panelMaxPos: 0,
+ canScroll: true
+ };
+
+ this.gantt = null;
+ this.loader = null;
+
+ core.create(this);
+
+ });
+
+ };
+})(jQuery);
+
+function ktkGetNextDate(currentDate, scaleStep) {
+ for(var minIncrements = 1;; minIncrements++) {
+ var nextDate = new Date(currentDate);
+ nextDate.setHours(currentDate.getHours() + scaleStep * minIncrements);
+
+ if(nextDate.getTime() != currentDate.getTime()) {
+ return nextDate;
+ }
+
+ // If code reaches here, it's because current didn't really increment (invalid local time) because of daylight-saving adjustments
+ // => retry adding 2, 3, 4 hours, and so on (until nextDate > current)
+ }
+}
1
0
25 Jun '13
See <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
Changes:
[Jean Couteau] #refs #931 : Add a Cancelled extension.
- Quotation can now get the Cancelled extension in sales funnel.
- Quotation status change in Sales funnel now gets a popup to precise values
- Still needs to update sales funnel amounts when using cancelled extension
------------------------------------------
[...truncated 342 lines...]
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 5; columnNumber: 17; The element type "link" must be terminated by the matching end-tag "</link>".
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] editQuotation.jsp~:4:1: Element type "link" must be followed by either attribute specifications, ">" or "/>".
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 1; Element type "link" must be followed by either attribute specifications, ">" or "/>".
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 1; Element type "link" must be followed by either attribute specifications, ">" or "/>".
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] salesReport.jsp~:4:37: The prefix "jsp" for element "jsp:include" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
[Fatal Error] salesPerAccountReport.jsp~:4:37: The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] sales.jsp~:2:43: The prefix "jsp" for element "jsp:include" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 2; columnNumber: 43; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 2; columnNumber: 43; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] dashboardVacationByEmployee.jsp~:5:63: The prefix "c" for element "c:forEach" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 5; columnNumber: 63; The prefix "c" for element "c:forEach" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 5; columnNumber: 63; The prefix "c" for element "c:forEach" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] hr.jsp~:9:71: The prefix "jsp" for element "jsp:include" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 9; columnNumber: 71; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 9; columnNumber: 71; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] salesPerProjectReport.jsp~:4:37: The prefix "jsp" for element "jsp:include" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] account.jsp~:3:74: The element type "link" must be terminated by the matching end-tag "</link>".
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 3; columnNumber: 74; The element type "link" must be terminated by the matching end-tag "</link>".
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 3; columnNumber: 74; The element type "link" must be terminated by the matching end-tag "</link>".
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] accountSalesReport.jsp~:4:37: The prefix "jsp" for element "jsp:include" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] acceptedQuotation.jsp~:4:37: The prefix "jsp" for element "jsp:include" is not bound.
[Fatal Error] sentQuotation.jsp~:4:37: The prefix "jsp" for element "jsp:include" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)[Fatal Error] report.jsp~:5:40: The prefix "c" for element "c:if" is not bound.
[Fatal Error] dashboardProfitability.jsp~:21:46: The prefix "c" for element "c:forEach" is not bound.
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
[Fatal Error] index.jsp~:6:50: The prefix "jsp" for element "jsp:include" is not bound.
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 21; columnNumber: 46; The prefix "c" for element "c:forEach" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 21; columnNumber: 46; The prefix "c" for element "c:forEach" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 5; columnNumber: 40; The prefix "c" for element "c:if" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 5; columnNumber: 40; The prefix "c" for element "c:if" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 6; columnNumber: 50; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…;> lineNumber: 6; columnNumber: 50; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[INFO]
[INFO] --- maven-i18n-plugin:2.3.1:get (get) @ chorem-webmotion ---
[INFO] Copying chorem-webmotion.properties to <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
[INFO] Copying chorem-webmotion.properties to <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
[INFO]
[INFO] --- maven-i18n-plugin:2.3.1:gen (gen-and-make-bundle) @ chorem-webmotion ---
[INFO] Copying chorem-webmotion_fr_FR.properties to <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
[INFO] Copying chorem-webmotion_en_GB.properties to <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
[INFO]
[INFO] --- maven-i18n-plugin:2.3.1:collect-i18n-artifacts (collect-i18n-artifacts) @ chorem-webmotion ---
Downloading: http://nexus.nuiton.org/nexus/content/groups/wikitty/org/nuiton/wikitty/3.1…
Downloading: http://nexus.nuiton.org/nexus/content/groups/wikitty/org/nuiton/wikitty/wik…
[INFO] collected 2 i18n artifacts for locale fr_FR stored in <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
[INFO] collected 2 i18n artifacts for locale en_GB stored in <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
[INFO]
[INFO] --- maven-i18n-plugin:2.3.1:bundle (gen-and-make-bundle) @ chorem-webmotion ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ chorem-webmotion ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 4 resources
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ chorem-webmotion ---
[INFO] Compiling 34 source files to <http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] bootstrap class path not set in conjunction with -source 1.6
<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>:[34,26] error: cannot find symbol
[ERROR] symbol: class Cancelled
location: package org.chorem.entities
<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>:[114,8] error: cannot find symbol
[ERROR] symbol: class Cancelled
location: class SalesAction
<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>:[114,45] error: cannot find symbol
[ERROR] symbol: class Cancelled
location: class SalesAction
<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>:[28,23] error: cannot find symbol
[ERROR] symbol: variable Cancelled
location: class FunnelAction
<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>:[46,23] error: cannot find symbol
[ERROR] symbol: variable Cancelled
location: class FunnelAction
<http://ci.nuiton.org/jenkins/job/chorem/org.chorem.chorem$chorem-webmotion/…>:[65,23] error: cannot find symbol
[INFO] 6 errors
[INFO] -------------------------------------------------------------
1
2
See <http://ci.nuiton.org/jenkins/job/chorem/141/changes>
Changes:
[Jean Couteau] #refs #931 : Add a Cancelled extension.
- Quotation can now get the Cancelled extension in sales funnel.
- Quotation status change in Sales funnel now gets a popup to precise values
- Still needs to update sales funnel amounts when using cancelled extension
------------------------------------------
[...truncated 806 lines...]
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] dashboardVacationByEmployee.jsp~:5:63: The prefix "c" for element "c:forEach" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 5; columnNumber: 63; The prefix "c" for element "c:forEach" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 5; columnNumber: 63; The prefix "c" for element "c:forEach" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] hr.jsp~:9:71: The prefix "jsp" for element "jsp:include" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 9; columnNumber: 71; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 9; columnNumber: 71; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] salesPerProjectReport.jsp~:4:37: The prefix "jsp" for element "jsp:include" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] account.jsp~:3:74: The element type "link" must be terminated by the matching end-tag "</link>".
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 3; columnNumber: 74; The element type "link" must be terminated by the matching end-tag "</link>".
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 3; columnNumber: 74; The element type "link" must be terminated by the matching end-tag "</link>".
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] accountSalesReport.jsp~:4:37: The prefix "jsp" for element "jsp:include" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[Fatal Error] acceptedQuotation.jsp~:4:37: The prefix "jsp" for element "jsp:include" is not bound.
[Fatal Error] sentQuotation.jsp~:4:37: The prefix "jsp" for element "jsp:include" is not bound.
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)[Fatal Error] report.jsp~:5:40: The prefix "c" for element "c:if" is not bound.
[Fatal Error] dashboardProfitability.jsp~:21:46: The prefix "c" for element "c:forEach" is not bound.
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
[Fatal Error] index.jsp~:6:50: The prefix "jsp" for element "jsp:include" is not bound.
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 4; columnNumber: 37; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 21; columnNumber: 46; The prefix "c" for element "c:forEach" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 21; columnNumber: 46; The prefix "c" for element "c:forEach" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
[ERROR] could not parse file <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 5; columnNumber: 40; The prefix "c" for element "c:if" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 5; columnNumber: 40; The prefix "c" for element "c:if" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
org.nuiton.i18n.plugin.parser.ParserException: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 6; columnNumber: 50; The prefix "jsp" for element "jsp:include" is not bound.
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:400)
at org.nuiton.i18n.plugin.parser.ParserExecutor$ParserTask.run(ParserExecutor.java:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.xml.sax.SAXParseException; systemId: file://<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…;> lineNumber: 6; columnNumber: 50; The prefix "jsp" for element "jsp:include" is not bound.
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:251)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:300)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:177)
at org.nuiton.i18n.plugin.parser.impl.AbstractParserXmlMojo$XmlFileParser.parseFile(AbstractParserXmlMojo.java:387)
... 4 more
[INFO]
[INFO] --- maven-i18n-plugin:2.3.1:get (get) @ chorem-webmotion ---
[INFO] Copying chorem-webmotion.properties to <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/ge…>
[INFO] Copying chorem-webmotion.properties to <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/ge…>
[INFO]
[INFO] --- maven-i18n-plugin:2.3.1:gen (gen-and-make-bundle) @ chorem-webmotion ---
[INFO] Copying chorem-webmotion_fr_FR.properties to <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
[INFO] Copying chorem-webmotion_en_GB.properties to <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/src/main/…>
[INFO]
[INFO] --- maven-i18n-plugin:2.3.1:collect-i18n-artifacts (collect-i18n-artifacts) @ chorem-webmotion ---
Downloading: http://nexus.nuiton.org/nexus/content/groups/wikitty/org/nuiton/wikitty/3.1…
Downloading: http://nexus.nuiton.org/nexus/content/groups/wikitty/org/nuiton/wikitty/wik…
[INFO] collected 2 i18n artifacts for locale fr_FR stored in <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…>
[INFO] collected 2 i18n artifacts for locale en_GB stored in <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/i1…>
[INFO]
[INFO] --- maven-i18n-plugin:2.3.1:bundle (gen-and-make-bundle) @ chorem-webmotion ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ chorem-webmotion ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 4 resources
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ chorem-webmotion ---
[INFO] Compiling 34 source files to <http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/cl…>
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] bootstrap class path not set in conjunction with -source 1.6
<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/pr…>:[34,26] error: cannot find symbol
[ERROR] symbol: class Cancelled
location: package org.chorem.entities
<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/pr…>:[114,8] error: cannot find symbol
[ERROR] symbol: class Cancelled
location: class SalesAction
<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/pr…>:[114,45] error: cannot find symbol
[ERROR] symbol: class Cancelled
location: class SalesAction
<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/pr…>:[28,23] error: cannot find symbol
[ERROR] symbol: variable Cancelled
location: class FunnelAction
<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/pr…>:[46,23] error: cannot find symbol
[ERROR] symbol: variable Cancelled
location: class FunnelAction
<http://ci.nuiton.org/jenkins/job/chorem/ws/trunk/chorem-webmotion/target/pr…>:[65,23] error: cannot find symbol
[INFO] 6 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] chorem ............................................ SUCCESS [3.161s]
[INFO] Chorem entities ................................... SUCCESS [11.602s]
[INFO] Chorem webmotion .................................. FAILURE [5.508s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 20.950s
[INFO] Finished at: Fri Jun 21 22:46:16 CEST 2013
[INFO] Final Memory: 37M/289M
[INFO] ------------------------------------------------------------------------
[JENKINS] Archiving disabled
[JENKINS] Archiving disabled
[JENKINS] Archiving disabled
Waiting for Jenkins to finish collecting data
mavenExecutionResult exceptions not empty
message : Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.5.1:compile (default-compile) on project chorem-webmotion: Compilation failure
cause : Compilation failure
Stack trace :
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.5.1:compile (default-compile) on project chorem-webmotion: Compilation failure
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:213)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.jvnet.hudson.maven3.launcher.Maven3Launcher.main(Maven3Launcher.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchStandard(Launcher.java:329)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:239)
at org.jvnet.hudson.maven3.agent.Maven3Main.launch(Maven3Main.java:158)
at hudson.maven.Maven3Builder.call(Maven3Builder.java:100)
at hudson.maven.Maven3Builder.call(Maven3Builder.java:66)
at hudson.remoting.UserRequest.perform(UserRequest.java:118)
at hudson.remoting.UserRequest.perform(UserRequest.java:48)
at hudson.remoting.Request$2.run(Request.java:326)
at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.apache.maven.plugin.CompilationFailureException: Compilation failure
at org.apache.maven.plugin.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:729)
at org.apache.maven.plugin.CompilerMojo.execute(CompilerMojo.java:128)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
... 27 more
Sending e-mails to: chorem-commits(a)list.chorem.org
channel stopped
1
2
Author: jcouteau
Date: 2013-06-25 11:55:33 +0200 (Tue, 25 Jun 2013)
New Revision: 346
Url: http://chorem.org/projects/chorem/repository/revisions/346
Log:
refs #931 : Commit model
Modified:
trunk/chorem-entities/src/main/xmi/chorem-model.properties
trunk/chorem-entities/src/main/xmi/chorem-model.zargo
Modified: trunk/chorem-entities/src/main/xmi/chorem-model.properties
===================================================================
--- trunk/chorem-entities/src/main/xmi/chorem-model.properties 2013-06-21 20:02:35 UTC (rev 345)
+++ trunk/chorem-entities/src/main/xmi/chorem-model.properties 2013-06-25 09:55:33 UTC (rev 346)
@@ -35,6 +35,13 @@
org.chorem.entities.Attachment.attribute.content.tagvalue.help=Le fichier \u00e0 importer
org.chorem.entities.Attachment.attribute.contentUrl.tagvalue.help=Si on ne souhaite pas importer le fichier, on peut indiquer ici sont URL (ex: http://commun.codelutin.home/Clients/...)
#
+# Cancelled
+#
+org.chorem.entities.Cancelled.class.tagvalue.version=1.0
+org.chorem.entities.Cancelled.class.tagvalue.toString=%Quotation.description|nologin$s
+org.chorem.entities.Cancelled.class.tagvalue.sortOrder=Cancelled.cancelledDate
+
+#
# category
#
org.chorem.entities.Category.class.tagvalue.version=5.0
Modified: trunk/chorem-entities/src/main/xmi/chorem-model.zargo
===================================================================
(Binary files differ)
1
0
r345 - in trunk/chorem-webmotion/src/main: java/org/chorem/webmotion/actions/sales webapp/WEB-INF/jsp/salesReports webapp/js
by jcouteau@users.chorem.org 21 Jun '13
by jcouteau@users.chorem.org 21 Jun '13
21 Jun '13
Author: jcouteau
Date: 2013-06-21 22:02:35 +0200 (Fri, 21 Jun 2013)
New Revision: 345
Url: http://chorem.org/projects/chorem/repository/revisions/345
Log:
#refs #931 : Add a Cancelled extension.
- Quotation can now get the Cancelled extension in sales funnel.
- Quotation status change in Sales funnel now gets a popup to precise values
- Still needs to update sales funnel amounts when using cancelled extension
Modified:
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/FunnelAction.java
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesAction.java
trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/salesReports/salesFunnel.jsp
trunk/chorem-webmotion/src/main/webapp/js/chorem.js
Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/FunnelAction.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/FunnelAction.java 2013-06-20 14:35:02 UTC (rev 344)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/FunnelAction.java 2013-06-21 20:02:35 UTC (rev 345)
@@ -1,11 +1,7 @@
package org.chorem.webmotion.actions.sales;
import org.chorem.ChoremClient;
-import org.chorem.entities.Accepted;
-import org.chorem.entities.Draft;
-import org.chorem.entities.Quotation;
-import org.chorem.entities.Rejected;
-import org.chorem.entities.Sent;
+import org.chorem.entities.*;
import org.debux.webmotion.server.WebMotionController;
import org.debux.webmotion.server.render.Render;
import org.nuiton.wikitty.query.WikittyQuery;
@@ -29,6 +25,7 @@
WikittyQuery leadQuotationQuery = new WikittyQueryMaker().and()
.exteq(Quotation.EXT_QUOTATION)
.extne(Draft.EXT_DRAFT)
+ .extne(Cancelled.EXT_CANCELLED)
.end().setLimit(WikittyQuery.MAX);
WikittyQueryResult<Quotation> leads =
@@ -46,6 +43,7 @@
WikittyQuery draftQuotationQuery = new WikittyQueryMaker().and()
.exteq(Draft.EXT_DRAFT)
.extne(Sent.EXT_SENT)
+ .extne(Cancelled.EXT_CANCELLED)
.end().setLimit(WikittyQuery.MAX);
WikittyQueryResult<Quotation> drafts =
@@ -64,6 +62,7 @@
.exteq(Sent.EXT_SENT)
.extne(Accepted.EXT_ACCEPTED)
.extne(Rejected.EXT_REJECTED)
+ .extne(Cancelled.EXT_CANCELLED)
.end().setLimit(WikittyQuery.MAX);
WikittyQueryResult<Quotation> sents =
Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesAction.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesAction.java 2013-06-20 14:35:02 UTC (rev 344)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesAction.java 2013-06-21 20:02:35 UTC (rev 345)
@@ -23,16 +23,21 @@
* #L%
*/
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.chorem.ChoremClient;
import org.chorem.entities.Accepted;
import org.chorem.entities.Draft;
import org.chorem.entities.Rejected;
import org.chorem.entities.Sent;
import org.chorem.entities.Started;
+import org.chorem.entities.Cancelled;
import org.chorem.webmotion.render.RenderWikittyJson;
import org.debux.webmotion.server.WebMotionController;
import org.debux.webmotion.server.render.Render;
+import org.nuiton.wikitty.WikittyUtil;
+import java.text.ParseException;
import java.util.Date;
/**
@@ -45,23 +50,40 @@
*/
public class SalesAction extends WebMotionController {
- public Render send(ChoremClient client, String id) {
+ static private Log log = LogFactory.getLog(SalesAction.class);
+
+ public Render send(ChoremClient client, String id, String sendingDate) {
Sent sent = client.restore(Sent.class, id);
- sent.setPostedDate(new Date());
+ try {
+ sent.setPostedDate(WikittyUtil.parseDate(sendingDate));
+ } catch (ParseException e) {
+ log.debug("Could not parse date : " + sendingDate);
+ getContext().addInfoMessage("message", "Warning: Could not parse date " + sendingDate);
+ }
sent = client.store(sent);
return new RenderWikittyJson(sent);
}
- public Render accept(ChoremClient client, String id) {
+ public Render accept(ChoremClient client, String id, String acceptedDate) {
Accepted accepted = client.restore(Accepted.class, id);
- accepted.setAcceptedDate(new Date());
+ try {
+ accepted.setAcceptedDate(WikittyUtil.parseDate(acceptedDate));
+ } catch (ParseException e) {
+ log.debug("Could not parse date : " + acceptedDate);
+ getContext().addInfoMessage("message", "Warning: Could not parse date " + acceptedDate);
+ }
client.store(accepted);
return new RenderWikittyJson(accepted);
}
- public Render reject(ChoremClient client, String id) {
+ public Render reject(ChoremClient client, String id, String rejectedDate) {
Rejected rejected = client.restore(Rejected.class, id);
- rejected.setRejectedDate(new Date());
+ try {
+ rejected.setRejectedDate(WikittyUtil.parseDate(rejectedDate));
+ } catch (ParseException e) {
+ log.debug("Could not parse date : " + rejectedDate);
+ getContext().addInfoMessage("message", "Warning: Could not parse date " + rejectedDate);
+ }
client.store(rejected);
return new RenderWikittyJson(rejected);
}
@@ -73,9 +95,31 @@
return new RenderWikittyJson(started);
}
- public Render answer(ChoremClient client, String id) {
+ public Render answer(ChoremClient client, String id, String sendingDate,
+ String reference) {
Draft draft = client.restore(Draft.class, id,".*");
+ try {
+ draft.setSendingDate(WikittyUtil.parseDate(sendingDate));
+ } catch (ParseException e) {
+ log.debug("Could not parse date : " + sendingDate);
+ getContext().addInfoMessage("message", "Warning: Could not parse date " + sendingDate);
+ }
+ draft.setReference(reference);
draft = client.store(draft);
return new RenderWikittyJson(draft);
}
+
+ public Render cancel(ChoremClient client, String id, String cancelledDate,
+ String reason) {
+ Cancelled cancelled = client.restore(Cancelled.class, id, ".*");
+ try {
+ cancelled.setCancelledDate(WikittyUtil.parseDate(cancelledDate));
+ } catch (ParseException e) {
+ log.debug("Could not parse date : " + cancelledDate);
+ getContext().addInfoMessage("message", "Warning: Could not parse date " + cancelledDate);
+ }
+ cancelled.setReason(reason);
+ cancelled = client.store(cancelled);
+ return new RenderWikittyJson(cancelled);
+ }
}
Modified: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/salesReports/salesFunnel.jsp
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/salesReports/salesFunnel.jsp 2013-06-20 14:35:02 UTC (rev 344)
+++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/salesReports/salesFunnel.jsp 2013-06-21 20:02:35 UTC (rev 345)
@@ -72,6 +72,7 @@
</p>
</div>
<a class="btn btn-success pull-right salesFunnelItemButton lead" wikittyId="${q.wikittyId}">Répondre</a>
+ <a class="btn btn-warning pull-right salesFunnelItemButton toCancelled" wikittyId="${q.wikittyId}">Annuler</a>
<div class="pull-right salesFunnelItemPrice">
<p class="salesFunnelItemTitle">
<w:display wikitty="${q.wikitty}" fqfield="Quotation.amount" label=""/>
@@ -99,6 +100,7 @@
<p><span class="salesFunnelItemTitle"><a class="name-link" href="<c:url value="/wikitty/Project/view/${q.project}"/>"><w:display wikitty="${q.wikitty}" fqfield="Quotation.project" label=""/></a></span> - <small><w:display wikitty="${q.wikitty}" fqfield="Quotation.description" label=""/></small></p>
</div>
<a class="btn btn-success pull-right salesFunnelItemButton draft" wikittyId="${q.wikittyId}">Envoyer</a>
+ <a class="btn btn-warning pull-right salesFunnelItemButton toCancelled" wikittyId="${q.wikittyId}">Annuler</a>
<div class="pull-right salesFunnelItemPrice">
<p class="salesFunnelItemTitle"><w:display wikitty="${q.wikitty}" fqfield="Quotation.amount" label=""/></p>
<small><w:display wikitty="${q.wikitty}" fqfield="Quotation.category" label=""/> - <w:display wikitty="${q.wikitty}" fqfield="Quotation.estimatedDays" label=""/>j - <w:display wikitty="${q.wikitty}" fqfield="Quotation.conversionHope" label=""/></small>
@@ -122,6 +124,7 @@
</div>
<a class="btn btn-success pull-right salesFunnelItemButton sent toAccepted" wikittyId="${q.wikittyId}">Accepté</a>
<a class="btn btn-danger pull-right salesFunnelItemButton sent toRejected" wikittyId="${q.wikittyId}">Rejeté</a>
+ <a class="btn btn-warning pull-right salesFunnelItemButton toCancelled" wikittyId="${q.wikittyId}">Annuler</a>
<div class="pull-right salesFunnelItemPrice">
<p class="salesFunnelItemTitle"><w:display wikitty="${q.wikitty}" fqfield="Quotation.amount" label=""/></p>
<small><w:display wikitty="${q.wikitty}" fqfield="Quotation.category" label=""/> - <w:display wikitty="${q.wikitty}" fqfield="Quotation.estimatedDays" label=""/>j - <w:display wikitty="${q.wikitty}" fqfield="Quotation.conversionHope" label=""/></small>
@@ -132,6 +135,60 @@
</ul>
</div>
+ <div id="dialog-form-leadToDraft" title="Proposition commerciale à envoyer">
+ <form>
+ <fieldset>
+ <label for="sendingDate">Date d'envoi</label>
+ <input type="text" name="sendingDate" id="sendingDate" class="datepicker" />
+ <label for="reference">Référence</label>
+ <input type="text" name="reference" id="reference" value="" class="text ui-widget-content ui-corner-all" />
+ <input type="hidden" name="id" id="lead-wikittyId"/>
+ </fieldset>
+ </form>
+ </div>
+
+ <div id="dialog-form-draftToSent" title="Proposition commerciale envoyée">
+ <form>
+ <fieldset>
+ <label for="sendDate">Date d'envoi</label>
+ <input type="text" name="sendDate" id="sendDate" class="datepicker" />
+ <input type="hidden" name="id" id="draft-wikittyId"/>
+ </fieldset>
+ </form>
+ </div>
+
+ <div id="dialog-form-sentToAccepted" title="Proposition commerciale acceptée">
+ <form>
+ <fieldset>
+ <label for="acceptedDate">Date d'acceptation</label>
+ <input type="text" name="acceptedDate" id="acceptedDate" class="datepicker" />
+ <input type="hidden" name="id" id="sent-wikittyId"/>
+ </fieldset>
+ </form>
+ </div>
+
+ <div id="dialog-form-sentToRejected" title="Proposition commerciale refusée">
+ <form>
+ <fieldset>
+ <label for="rejectedDate">Date de refus</label>
+ <input type="text" name="rejectedDate" id="rejectedDate" class="datepicker" />
+ <input type="hidden" name="id" id="rejected-wikittyId"/>
+ </fieldset>
+ </form>
+ </div>
+
+ <div id="dialog-form-toCancelled" title="Proposition commerciale annulée">
+ <form>
+ <fieldset>
+ <label for="cancelledDate">Date d'annulation</label>
+ <input type="text" name="cancelledDate" id="cancelledDate" class="datepicker" />
+ <label for="cancelledReason">Raison</label>
+ <input type="text" name="cancelledReason" id="cancelledReason" value="" class="text ui-widget-content ui-corner-all" />
+ <input type="hidden" name="id" id="cancelled-wikittyId"/>
+ </fieldset>
+ </form>
+ </div>
+
</div>
</div>
Modified: trunk/chorem-webmotion/src/main/webapp/js/chorem.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/chorem.js 2013-06-20 14:35:02 UTC (rev 344)
+++ trunk/chorem-webmotion/src/main/webapp/js/chorem.js 2013-06-21 20:02:35 UTC (rev 345)
@@ -93,6 +93,44 @@
});
}
});
+
+
+/*********** SALES FUNNEL FUNCTIONS**********************/
+function leadToDraft(){
+ var id = $(this).attr('wikittyId');
+ var oldQuotation = $(this).parent();
+ $("#lead-wikittyId").val(id);
+ $("#dialog-form-leadToDraft" ).data("oldQuotation", oldQuotation).dialog( "open" );
+};
+
+function draftToSent(){
+ var id = $(this).attr('wikittyId');
+ var oldQuotation = $(this).parent();
+ $("#draft-wikittyId").val(id);
+ $("#dialog-form-draftToSent" ).data("oldQuotation", oldQuotation).dialog( "open" );
+};
+
+function sentToAccepted(){
+ var id = $(this).attr('wikittyId');
+ var oldQuotation = $(this).parent();
+ $("#sent-wikittyId").val(id);
+ $("#dialog-form-sentToAccepted" ).data("oldQuotation", oldQuotation).dialog( "open" );
+};
+
+function sentToRejected(){
+ var id = $(this).attr('wikittyId');
+ var oldQuotation = $(this).parent();
+ $("#rejected-wikittyId").val(id);
+ $("#dialog-form-sentToRejected" ).data("oldQuotation", oldQuotation).dialog( "open" );
+};
+
+function toCancelled(){
+ var id = $(this).attr('wikittyId');
+ var oldQuotation = $(this).parent();
+ $("#cancelled-wikittyId").val(id);
+ $("#dialog-form-toCancelled" ).data("oldQuotation", oldQuotation).dialog( "open" );
+};
+
//ajout ble
//clic sur les cases à cocher half-day d'une vacation (VacationRequest)
@@ -106,7 +144,6 @@
dt.val(dtVal);
}
-
$(document).ready(function() {
$('.beginDateTR :checkbox').change(function(){
var dtetim = $(this).parent().parent().children('.beginDateTD').children('input');
@@ -233,260 +270,447 @@
// * SALES FUNNEL *
// ********************************************************************
- function leadToDraft() {
- var id = $(this).attr('wikittyId');
- var oldQuotation = $(this).parent();
- $.get(createUrl("/sales/funnel/json/answer/", id),
- function(data){
- //success
- var wikittyId = data.meta.id;
- var wikitty = data.data;
+
+ //Passage d'un lead -> draft
+ $("a.lead").click(leadToDraft);
- var li = $("<li></li>").addClass("salesFunnelItem draft");
+ $( "#dialog-form-leadToDraft" ).dialog({
+ autoOpen: false,
+ height: 300,
+ width: 350,
+ modal: true,
+ buttons: {
+ Ok: function() {
- //leftDiv
- var leftDiv = $("<div></div>").addClass("pull-left");
- var aIconEdit = $("<a></a>")
- .attr("href", createUrl("/wikitty/edit/", wikittyId));
- var iconEdit = $("<i></i>").addClass("icon-edit");
- aIconEdit.append(iconEdit);
- leftDiv.append(aIconEdit);
- var smallAccount = $("<small></small>");
- if (wikitty["Quotation.customer"]!=null){
- var customer = data.preloaded[wikitty["Quotation.customer"]];
- var firstName = customer.preloaded[customer.data["Employee.person"]].data["Person.firstName"];
- var lastName = customer.preloaded[customer.data["Employee.person"]].data["Person.lastName"];
- var company = customer.preloaded[customer.data["Employee.company"]].data["Company.name"];
- }
- var aAccount = $("<a></a>")
- .text(firstName + " " + lastName + " (" + company + ")")
- .attr("href",createUrl("/wikitty/Employee/view/", wikitty["Quotation.customer"]));
- smallAccount.append(aAccount);
- leftDiv.append(smallAccount);
- var leftP = $("<p> - </p>");
- var itemTitleSpan = $('<span></span>').addClass('salesFunnelItemTitle');
+ var reference = $("#reference").val();
+ var sendingDate = $("#sendingDate").val();
+ var id = $("#lead-wikittyId").val();
+ var oldQuotation = $(this).data('oldQuotation');
+ var allFields = $([]).add($("#reference")).add($("#sendingDate")).add($("#lead-wikittyId"))
- if (wikitty["Quotation.project"]!=null) {
- var aProject = $("<a/>")
- .addClass("nameLink")
- .attr("href" , createUrl("/wikitty/Project/view/", wikitty["Quotation.project"]))
- .text(data.preloaded[wikitty["Quotation.project"]].data["Project.name"]);
- }
- itemTitleSpan.append(aProject);
- var descriptionSmall = $('<small/>').text(wikitty["Quotation.description"]);
- leftP.append(descriptionSmall);
- leftP.prepend(itemTitleSpan);
- leftDiv.append(leftP);
+ var dialog = $( this );
- //button
- var aSend = $('<a/>')
- .attr('wikittyId', wikittyId)
- .addClass("btn btn-success pull-right salesFunnelItemButton draft")
- .text("Envoyer")
- .click(draftToSent);
+ $.post(createUrl("/sales/funnel/json/answer/", id,"?sendingDate=", sendingDate, "&reference=",reference),
+ function(data){
+ //success
+ var wikittyId = data.meta.id;
+ var wikitty = data.data;
- //rightDiv
- var rightDiv = $("<div>").addClass("pull-right");
- var rightP = $("<p>").addClass("salesFunnelItemTitle").text(wikitty["Quotation.amount"] +" €");
- if (wikitty["Quotation.category"] != null) {
- var smallInfo = $("<small>")
- .text(data.preloaded[wikitty["Quotation.category"]].data["WikittyTreeNode.name"]
- + ' - ' + wikitty["Quotation.estimatedDays"] + 'j - ' +
- wikitty["Quotation.conversionHope"] + "%");
- }
- rightDiv.append(rightP);
- rightDiv.append(smallInfo);
+ var li = $("<li></li>").addClass("salesFunnelItem draft");
- //clear:both
- var clearBoth=$("<div style='clear:both;'/>")
+ //leftDiv
+ var leftDiv = $("<div></div>").addClass("pull-left");
+ var aIconEdit = $("<a></a>")
+ .attr("href", createUrl("/wikitty/edit/", wikittyId));
+ var iconEdit = $("<i></i>").addClass("icon-edit");
+ aIconEdit.append(iconEdit);
+ leftDiv.append(aIconEdit);
+ var smallAccount = $("<small></small>");
+ if (wikitty["Quotation.customer"]!=null){
+ var customer = data.preloaded[wikitty["Quotation.customer"]];
+ var firstName = customer.preloaded[customer.data["Employee.person"]].data["Person.firstName"];
+ var lastName = customer.preloaded[customer.data["Employee.person"]].data["Person.lastName"];
+ var company = customer.preloaded[customer.data["Employee.company"]].data["Company.name"];
+ }
+ var aAccount = $("<a></a>")
+ .text(firstName + " " + lastName + " (" + company + ")")
+ .attr("href",createUrl("/wikitty/Employee/view/", wikitty["Quotation.customer"]));
+ smallAccount.append(aAccount);
+ leftDiv.append(smallAccount);
+ var leftP = $("<p> - </p>");
+ var itemTitleSpan = $('<span></span>').addClass('salesFunnelItemTitle');
- li.append(leftDiv);
- li.append(aSend);
- li.append(rightDiv);
- li.append(clearBoth);
+ if (wikitty["Quotation.project"]!=null) {
+ var aProject = $("<a/>")
+ .addClass("nameLink")
+ .attr("href" , createUrl("/wikitty/Project/view/", wikitty["Quotation.project"]))
+ .text(data.preloaded[wikitty["Quotation.project"]].data["Project.name"]);
+ }
+ itemTitleSpan.append(aProject);
+ var descriptionSmall = $('<small/>').text(wikitty["Quotation.description"]);
+ leftP.append(descriptionSmall);
+ leftP.prepend(itemTitleSpan);
+ leftDiv.append(leftP);
- var drafts = $(".drafts");
- drafts.append(li);
- oldQuotation.slideUp();
+ //button
+ var aSend = $('<a/>')
+ .attr('wikittyId', wikittyId)
+ .addClass("btn btn-success pull-right salesFunnelItemButton draft")
+ .text("Envoyer")
+ .click(draftToSent);
- //update draftAmount and draftAmountHope
- var draftAmount = parseInt($("#draftAmount").text()) + wikitty["Quotation.amount"];
- var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
- var draftAmountHope = parseInt($("#draftAmountHope").text()) + amountHope;
- $("#draftAmount").text(draftAmount);
- $("#draftAmountHope").text(draftAmountHope);
+ var aCancelled = $('<a/>')
+ .attr('wikittyId', wikittyId)
+ .addClass("btn btn-warning pull-right salesFunnelItemButton toCancelled")
+ .text("Annuler")
+ .click(toCancelled);
- //update leadAmount and leadAmountHope
- var leadAmount = parseInt($("#leadAmount").text()) - wikitty["Quotation.amount"];
- var leadAmountHope = parseInt($("#leadAmountHope").text()) - amountHope;
- $("#leadAmount").text(leadAmount);
- $("#leadAmountHope").text(leadAmountHope);
+ //rightDiv
+ var rightDiv = $("<div>").addClass("pull-right");
+ var rightP = $("<p>").addClass("salesFunnelItemTitle").text(wikitty["Quotation.amount"] +" €");
+ if (wikitty["Quotation.category"] != null) {
+ var smallInfo = $("<small>")
+ .text(data.preloaded[wikitty["Quotation.category"]].data["WikittyTreeNode.name"]
+ + ' - ' + wikitty["Quotation.estimatedDays"] + 'j - ' +
+ wikitty["Quotation.conversionHope"] + "%");
+ }
+ rightDiv.append(rightP);
+ rightDiv.append(smallInfo);
- }).fail(function(){
- //fail
- //TODO JC20130212 retour utilisateur
- });
- }
+ //clear:both
+ var clearBoth=$("<div style='clear:both;'/>")
- function draftToSent() {
- var id = $(this).attr('wikittyId');
- var oldQuotation = $(this).parent();
- $.get(createUrl("/sales/funnel/json/send/", id),
- function(data){
- //success
+ li.append(leftDiv);
+ li.append(aSend);
+ li.append(aCancelled);
+ li.append(rightDiv);
+ li.append(clearBoth);
- var wikittyId = data.meta.id;
- var wikitty = data.data;
+ var drafts = $(".drafts");
+ drafts.append(li);
+ oldQuotation.slideUp();
- var li = $("<li></li>").addClass("salesFunnelItem draft");
+ //update draftAmount and draftAmountHope
+ var draftAmount = parseInt($("#draftAmount").text()) + wikitty["Quotation.amount"];
+ var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
+ var draftAmountHope = parseInt($("#draftAmountHope").text()) + amountHope;
+ $("#draftAmount").text(draftAmount);
+ $("#draftAmountHope").text(draftAmountHope);
- //leftDiv
- var leftDiv = $("<div></div>").addClass("pull-left");
- var aIconEdit = $("<a></a>")
- .attr("href",createUrl("/wikitty/edit/", wikittyId));
- var iconEdit = $("<i></i>").addClass("icon-edit");
- aIconEdit.append(iconEdit);
- leftDiv.append(aIconEdit);
- var smallAccount = $("<small></small>");
- if (wikitty["Quotation.customer"]!=null){
- var customer = data.preloaded[wikitty["Quotation.customer"]];
- var firstName = customer.preloaded[customer.data["Employee.person"]].data["Person.firstName"];
- var lastName = customer.preloaded[customer.data["Employee.person"]].data["Person.lastName"];
- var company = customer.preloaded[customer.data["Employee.company"]].data["Company.name"];
- }
- var aAccount = $("<a></a>")
- .text(firstName + " " + lastName + " (" + company + ")")
- .attr("href", createUrl("/wikitty/Employee/view/", wikitty["Quotation.customer"]));
- smallAccount.append(aAccount);
- leftDiv.append(smallAccount);
- var leftP = $("<p> - </p>");
- var itemTitleSpan = $('<span></span>').addClass('salesFunnelItemTitle');
+ //update leadAmount and leadAmountHope
+ var leadAmount = parseInt($("#leadAmount").text()) - wikitty["Quotation.amount"];
+ var leadAmountHope = parseInt($("#leadAmountHope").text()) - amountHope;
+ $("#leadAmount").text(leadAmount);
+ $("#leadAmountHope").text(leadAmountHope);
- if (wikitty["Quotation.project"]!=null) {
- var aProject = $("<a/>")
- .addClass("nameLink")
- .attr("href" , createUrl("/wikitty/Project/view/", wikitty["Quotation.project"]))
- .text(data.preloaded[wikitty["Quotation.project"]].data["Project.name"]);
- }
- itemTitleSpan.append(aProject);
- var descriptionSmall = $('<small/>').text(wikitty["Quotation.description"]);
- leftP.append(descriptionSmall);
- leftP.prepend(itemTitleSpan);
- leftDiv.append(leftP);
+ allFields.val("");
- //button
- var aAccepted = $('<a/>')
- .attr('wikittyId', wikittyId)
- .addClass("btn btn-success pull-right salesFunnelItemButton sent toAccepted")
- .text("Accepté")
- .click(sentToAccepted);
- var aRejected = $('<a/>')
- .attr('wikittyId', wikittyId)
- .addClass("btn btn-danger pull-right salesFunnelItemButton sent toRejected")
- .text("Rejeté")
- .click(sentToRejected);
+ dialog.dialog( "close" );
- //rightDiv
- var rightDiv = $("<div>").addClass("pull-right");
- var rightP = $("<p>").addClass("salesFunnelItemTitle").text(wikitty["Quotation.amount"] +" €");
- if (wikitty["Quotation.category"] != null) {
- var smallInfo = $("<small>")
- .text(data.preloaded[wikitty["Quotation.category"]].data["WikittyTreeNode.name"]
- + ' - ' + wikitty["Quotation.estimatedDays"] + 'j - ' +
- wikitty["Quotation.conversionHope"] + "%");
- }
- rightDiv.append(rightP);
- rightDiv.append(smallInfo);
+ }).fail(function(){
+ //fail
+ //TODO JC20130212 retour utilisateur
+ dialog.dialog( "close" );
+ });
+ },
+ Cancel: function() {
+ $( this ).dialog( "close" );
+ }
+ },
+ close: function() {
+ },
+ open: function(event, ui) {
+ var date = new Date();
+ $("#sendingDate").val(date.getDate() + "/" + (date.getMonth()+1)+"/"+date.getFullYear());
+ }
+ });
- //clear:both
- var clearBoth=$("<div style='clear:both;'/>")
+ //Passage d'un draft -> sent
+ $("a.draft").click(draftToSent);
- li.append(leftDiv);
- li.append(aAccepted);
- li.append(aRejected);
- li.append(rightDiv);
- li.append(clearBoth);
+ $( "#dialog-form-draftToSent" ).dialog({
+ autoOpen: false,
+ height: 300,
+ width: 350,
+ modal: true,
+ buttons: {
+ Ok: function() {
- var sents = $(".sents");
- sents.append(li);
- oldQuotation.slideUp();
+ var sendingDate = $("#sendDate").val();
+ var id = $("#draft-wikittyId").val();
+ var oldQuotation = $(this).data('oldQuotation');
+ var allFields = $([]).add($("#sendDate")).add($("#draft-wikittyId"))
- //update draftAmount and draftAmountHope
- var draftAmount = parseInt($("#draftAmount").text()) - wikitty["Quotation.amount"];
- var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
- var draftAmountHope = parseInt($("#draftAmountHope").text()) - amountHope;
- $("#draftAmount").text(draftAmount);
- $("#draftAmountHope").text(draftAmountHope);
+ var dialog = $( this );
- //update sentAmount and sentAmountHope
- var sentAmount = parseInt($("#sentAmount").text()) + wikitty["Quotation.amount"];
- var sentAmountHope = parseInt($("#sentAmountHope").text()) + amountHope;
- $("#sentAmount").text(sentAmount);
- $("#sentAmountHope").text(sentAmountHope);
+ $.post(createUrl("/sales/funnel/json/send/", id,"?sendingDate=", sendingDate),
+ function(data){
+ //success
- }).fail(function(){
- //fail
- //TODO JC20130212 retour utilisateur
- });
- }
+ var wikittyId = data.meta.id;
+ var wikitty = data.data;
- function sentToRejected(){
- var id = $(this).attr('wikittyId');
- var oldQuotation = $(this).parent();
- $.get(createUrl("/sales/funnel/json/reject/", id),
- function(data){
- //success
- oldQuotation.slideUp();
+ var li = $("<li></li>").addClass("salesFunnelItem draft");
- var wikitty = data.data;
+ //leftDiv
+ var leftDiv = $("<div></div>").addClass("pull-left");
+ var aIconEdit = $("<a></a>")
+ .attr("href",createUrl("/wikitty/edit/", wikittyId));
+ var iconEdit = $("<i></i>").addClass("icon-edit");
+ aIconEdit.append(iconEdit);
+ leftDiv.append(aIconEdit);
+ var smallAccount = $("<small></small>");
+ if (wikitty["Quotation.customer"]!=null){
+ var customer = data.preloaded[wikitty["Quotation.customer"]];
+ var firstName = customer.preloaded[customer.data["Employee.person"]].data["Person.firstName"];
+ var lastName = customer.preloaded[customer.data["Employee.person"]].data["Person.lastName"];
+ var company = customer.preloaded[customer.data["Employee.company"]].data["Company.name"];
+ }
+ var aAccount = $("<a></a>")
+ .text(firstName + " " + lastName + " (" + company + ")")
+ .attr("href", createUrl("/wikitty/Employee/view/", wikitty["Quotation.customer"]));
+ smallAccount.append(aAccount);
+ leftDiv.append(smallAccount);
+ var leftP = $("<p> - </p>");
+ var itemTitleSpan = $('<span></span>').addClass('salesFunnelItemTitle');
- //update sentAmount and sentAmountHope
- var sentAmount = parseInt($("#sentAmount").text()) - wikitty["Quotation.amount"];
- var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
- var sentAmountHope = parseInt($("#sentAmountHope").text()) - amountHope;
- $("#sentAmount").text(sentAmount);
- $("#sentAmountHope").text(sentAmountHope);
- }).fail(function(){
- //fail
- //TODO JC20130212 retour utilisateur
- });
- }
+ if (wikitty["Quotation.project"]!=null) {
+ var aProject = $("<a/>")
+ .addClass("nameLink")
+ .attr("href" , createUrl("/wikitty/Project/view/", wikitty["Quotation.project"]))
+ .text(data.preloaded[wikitty["Quotation.project"]].data["Project.name"]);
+ }
+ itemTitleSpan.append(aProject);
+ var descriptionSmall = $('<small/>').text(wikitty["Quotation.description"]);
+ leftP.append(descriptionSmall);
+ leftP.prepend(itemTitleSpan);
+ leftDiv.append(leftP);
- function sentToAccepted(){
- var id = $(this).attr('wikittyId');
- var oldQuotation = $(this).parent();
- $.get(createUrl("/sales/funnel/json/accept/", id),
- function(data){
- //success
- oldQuotation.slideUp();
+ //button
+ var aAccepted = $('<a/>')
+ .attr('wikittyId', wikittyId)
+ .addClass("btn btn-success pull-right salesFunnelItemButton sent toAccepted")
+ .text("Accepté")
+ .click(sentToAccepted);
+ var aRejected = $('<a/>')
+ .attr('wikittyId', wikittyId)
+ .addClass("btn btn-danger pull-right salesFunnelItemButton sent toRejected")
+ .text("Rejeté")
+ .click(sentToRejected);
+ var aCancelled = $('<a/>')
+ .attr('wikittyId', wikittyId)
+ .addClass("btn btn-warning pull-right salesFunnelItemButton sent toCancelled")
+ .text("Annuler")
+ .click(toCancelled);
- var wikitty = data.data;
+ //rightDiv
+ var rightDiv = $("<div>").addClass("pull-right");
+ var rightP = $("<p>").addClass("salesFunnelItemTitle").text(wikitty["Quotation.amount"] +" €");
+ if (wikitty["Quotation.category"] != null) {
+ var smallInfo = $("<small>")
+ .text(data.preloaded[wikitty["Quotation.category"]].data["WikittyTreeNode.name"]
+ + ' - ' + wikitty["Quotation.estimatedDays"] + 'j - ' +
+ wikitty["Quotation.conversionHope"] + "%");
+ }
+ rightDiv.append(rightP);
+ rightDiv.append(smallInfo);
- //update sentAmount and sentAmountHope
- var sentAmount = parseInt($("#sentAmount").text()) - wikitty["Quotation.amount"];
- var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
- var sentAmountHope = parseInt($("#sentAmountHope").text()) - amountHope;
- $("#sentAmount").text(sentAmount);
- $("#sentAmountHope").text(sentAmountHope);
- }).fail(function(){
- //fail
- //TODO JC20130212 retour utilisateur
- });
- }
+ //clear:both
+ var clearBoth=$("<div style='clear:both;'/>")
- //Passage d'un lead -> draft
- $("a.lead").click(leadToDraft);
+ li.append(leftDiv);
+ li.append(aAccepted);
+ li.append(aRejected);
+ li.append(aCancelled);
+ li.append(rightDiv);
+ li.append(clearBoth);
- //Passage d'un draft -> sent
- $("a.draft").click(draftToSent);
+ var sents = $(".sents");
+ sents.append(li);
+ oldQuotation.slideUp();
- //Passage d'un sent vers accepted
- $("a.toAccepted").click(sentToAccepted);
+ //update draftAmount and draftAmountHope
+ var draftAmount = parseInt($("#draftAmount").text()) - wikitty["Quotation.amount"];
+ var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
+ var draftAmountHope = parseInt($("#draftAmountHope").text()) - amountHope;
+ $("#draftAmount").text(draftAmount);
+ $("#draftAmountHope").text(draftAmountHope);
- //Passage d'un sent vers rejected
- $("a.toRejected").click(sentToRejected);
+ //update sentAmount and sentAmountHope
+ var sentAmount = parseInt($("#sentAmount").text()) + wikitty["Quotation.amount"];
+ var sentAmountHope = parseInt($("#sentAmountHope").text()) + amountHope;
+ $("#sentAmount").text(sentAmount);
+ $("#sentAmountHope").text(sentAmountHope);
+ allFields.val("");
+ dialog.dialog( "close" );
+
+ }).fail(function(){
+ //fail
+ //TODO JC20130212 retour utilisateur
+ dialog.dialog( "close" );
+ });
+
+ },
+ Cancel: function() {
+ $( this ).dialog( "close" );
+ }
+ },
+ close: function() {
+ },
+ open: function(event, ui) {
+ var date = new Date();
+ $("#sendDate").val(date.getDate() + "/" + (date.getMonth()+1)+"/"+date.getFullYear());
+ }
+ });
+
+ //Passage d'un sent vers accepted
+ $("a.toAccepted").click(sentToAccepted);
+
+ $( "#dialog-form-sentToAccepted" ).dialog({
+ autoOpen: false,
+ height: 300,
+ width: 350,
+ modal: true,
+ buttons: {
+ Ok: function() {
+
+ var acceptedDate = $("#acceptedDate").val();
+ var id = $("#sent-wikittyId").val();
+ var oldQuotation = $(this).data('oldQuotation');
+ var allFields = $([]).add($("#acceptedDate")).add($("#sent-wikittyId"))
+
+ var dialog = $( this );
+
+ $.post(createUrl("/sales/funnel/json/accept/", id,"?acceptedDate=", acceptedDate),
+ function(data){
+ //success
+ oldQuotation.slideUp();
+
+ var wikitty = data.data;
+
+ //update sentAmount and sentAmountHope
+ var sentAmount = parseInt($("#sentAmount").text()) - wikitty["Quotation.amount"];
+ var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
+ var sentAmountHope = parseInt($("#sentAmountHope").text()) - amountHope;
+ $("#sentAmount").text(sentAmount);
+ $("#sentAmountHope").text(sentAmountHope);
+
+ allFields.val("");
+
+ dialog.dialog( "close" );
+
+ }).fail(function(){
+ //fail
+ //TODO JC20130212 retour utilisateur
+ dialog.dialog( "close" );
+ });
+
+ },
+ Cancel: function() {
+ $( this ).dialog( "close" );
+ }
+ },
+ close: function() {
+ },
+ open: function(event, ui) {
+ var date = new Date();
+ $("#acceptedDate").val(date.getDate() + "/" + (date.getMonth()+1)+"/"+date.getFullYear());
+ }
+ });
+
+ //Passage d'un sent vers rejected
+ $("a.toRejected").click(sentToRejected);
+
+ $( "#dialog-form-sentToRejected" ).dialog({
+ autoOpen: false,
+ height: 300,
+ width: 350,
+ modal: true,
+ buttons: {
+ Ok: function() {
+
+ var rejectedDate = $("#rejectedDate").val();
+ var id = $("#rejected-wikittyId").val();
+ var oldQuotation = $(this).data('oldQuotation');
+ var allFields = $([]).add($("#rejectedDate")).add($("#rejected-wikittyId"))
+
+ var dialog = $( this );
+
+ $.post(createUrl("/sales/funnel/json/reject/", id,"?rejectedDate=", rejectedDate),
+ function(data){
+ //success
+ oldQuotation.slideUp();
+
+ var wikitty = data.data;
+
+ //update sentAmount and sentAmountHope
+ var sentAmount = parseInt($("#sentAmount").text()) - wikitty["Quotation.amount"];
+ var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
+ var sentAmountHope = parseInt($("#sentAmountHope").text()) - amountHope;
+ $("#sentAmount").text(sentAmount);
+ $("#sentAmountHope").text(sentAmountHope);
+
+ allFields.val("");
+
+ dialog.dialog( "close" );
+
+ }).fail(function(){
+ //fail
+ //TODO JC20130212 retour utilisateur
+ dialog.dialog( "close" );
+ });
+
+ },
+ Cancel: function() {
+ $( this ).dialog( "close" );
+ }
+ },
+ close: function() {
+ },
+ open: function(event, ui) {
+ var date = new Date();
+ $("#rejectedDate").val(date.getDate() + "/" + (date.getMonth()+1)+"/"+date.getFullYear());
+ }
+ });
+
+ //Passage vers cancelled
+ $("a.toCancelled").click(toCancelled);
+
+ $( "#dialog-form-toCancelled" ).dialog({
+ autoOpen: false,
+ height: 300,
+ width: 350,
+ modal: true,
+ buttons: {
+ Ok: function() {
+
+ var cancelledDate = $("#cancelledDate").val();
+ var reason = $("#cancelledReason").val();
+ var id = $("#cancelled-wikittyId").val();
+ var oldQuotation = $(this).data('oldQuotation');
+ var allFields = $([]).add($("#cancelledDate")).add($("#cancelled-wikittyId")).add($("#cancelledReason"));
+
+ var dialog = $( this );
+
+ $.post(createUrl("/sales/funnel/json/cancel/", id,"?cancelledDate=", cancelledDate,"&reason=",reason),
+ function(data){
+ //success
+ oldQuotation.slideUp();
+
+ var wikitty = data.data;
+
+ //TODO JC20130527 update amounts
+ //update sentAmount and sentAmountHope
+ //var sentAmount = parseInt($("#sentAmount").text()) - wikitty["Quotation.amount"];
+ //var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
+ //var sentAmountHope = parseInt($("#sentAmountHope").text()) - amountHope;
+ //$("#sentAmount").text(sentAmount);
+ //$("#sentAmountHope").text(sentAmountHope);
+
+ allFields.val("");
+ dialog.dialog( "close" );
+
+ }).fail(function(){
+ //fail
+ //TODO JC20130212 retour utilisateur
+ dialog.dialog( "close" );
+ });
+
+ },
+ Cancel: function() {
+ $( this ).dialog( "close" );
+ }
+ },
+ close: function() {
+ },
+ open: function(event, ui) {
+ var date = new Date();
+ $("#cancelledDate").val(date.getDate() + "/" + (date.getMonth()+1)+"/"+date.getFullYear());
+ }
+ });
+
// ********************************************************************
// * PROJECT DASHBOARD *
// ********************************************************************
1
0
r344 - in trunk/chorem-webmotion/src/main/webapp/js: . jQueryGantt jQueryGantt/libs jQueryGantt/libs/JST jQueryGantt/libs/dateField jQueryGantt/libs/dateField/images
by meynier@users.chorem.org 20 Jun '13
by meynier@users.chorem.org 20 Jun '13
20 Jun '13
Author: meynier
Date: 2013-06-20 16:35:02 +0200 (Thu, 20 Jun 2013)
New Revision: 344
Url: http://chorem.org/projects/chorem/repository/revisions/344
Log:
Added jQueryGantt library
Added:
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/add.gif
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/alert.gif
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/closeBig.png
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/del.gif
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/edit.gif
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/gantt.css
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttDrawer.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttGridEditor.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttMaster.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttTask.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttUtilities.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/gantt_compact.css
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/hasExternalDeps.png
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/JST/
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/JST/jquery.JST.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/date.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/images/
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/images/next.png
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/images/prev.png
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/jquery.dateField.css
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/jquery.dateField.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/i18nJs.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/jquery.livequery.min.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/jquery.timers.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/platform.js
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/linkArrow.png
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/milestone.png
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/platform.css
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.eot
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.otf
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.svg
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.ttf
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.woff
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamworkFont.css
trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/twGanttSmall.png
Modified:
trunk/chorem-webmotion/src/main/webapp/js/chorem.js
Modified: trunk/chorem-webmotion/src/main/webapp/js/chorem.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/chorem.js 2013-06-20 10:37:21 UTC (rev 343)
+++ trunk/chorem-webmotion/src/main/webapp/js/chorem.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -500,34 +500,33 @@
function displayFields() {
var id = $(this).attr('wikittyId');
- $("#upgradeFields-" + id ).text("Loading fields for " + this.item(this.selectedIndex).label + "...");
- var extensionName = this.item(this.selectedIndex).label;
- $.get(createUrl("/project/json/getExtension/", extensionName, "/" + $(this).attr('wikittyId')),
- function(data){
- //success
- var el = document.createElement( 'div' );
- el.innerHTML = data;
+ if(this.selectedIndex == 0) {
+ $("#upgradeFields-" + id).text("");
+ }
+ else
+ {
- var view = el.getElementsByClassName("well")[0];
- var dateFields = view.getElementsByClassName("datepicker");
- var d = new Date();
- for(var i = 0; i < dateFields.length; i++) {
- dateFields[i].value = d.getDate() + "/" + (d.getMonth() +1) + "/" + d.getFullYear();
- //alert(dateFields[i].value);
- }
-
- $("#upgradeFields-" + id).html(view.innerHTML);
- initFields();
-
-
+ $("#upgradeFields-" + id ).text("Loading fields for " + this.item(this.selectedIndex).label + "...");
+ var extensionName = this.item(this.selectedIndex).label;
+ $.get(createUrl("/project/json/getExtension/", extensionName, "/" + $(this).attr('wikittyId')),
+ function(data){
+ //success
+ var $jData = $(data);
+
- });
+ $("#upgradeFields-" + id).html($jData.html());//.innerHTML);
+ initFields();
+
+
+
+ });
+ }
}
- $("a.upgrade").click(upgradeQuotation);
- $("select.extBox").change(displayFields);
- $("#project_hidden").change(function() {
- $("#projectSearch").submit();
- });
+$("a.upgrade").click(upgradeQuotation);
+$("select.extBox").change(displayFields);
+$("#project_hidden").change(function() {
+ $("#projectSearch").submit();
+});
});
\ No newline at end of file
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/add.gif
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/add.gif
___________________________________________________________________
Added: svn:mime-type
+ image/gif
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/alert.gif
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/alert.gif
___________________________________________________________________
Added: svn:mime-type
+ image/gif
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/closeBig.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/closeBig.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/del.gif
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/del.gif
___________________________________________________________________
Added: svn:mime-type
+ image/gif
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/edit.gif
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/edit.gif
___________________________________________________________________
Added: svn:mime-type
+ image/gif
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/gantt.css
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/gantt.css (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/gantt.css 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,323 @@
+.gdfTable {
+ table-layout: fixed;
+ border-collapse: separate;
+ border-spacing: 0;
+}
+
+.gdfTable td, .gdfTable th {
+ vertical-align: middle;
+ overflow: hidden;
+ text-overflow: clip;
+ white-space: nowrap;
+ font-size: 14px
+}
+
+.gdfCell {
+ overflow: hidden;
+ padding:4px 2px
+}
+
+.gdfColHeader {
+ min-width: 5px;
+ height: 30px;
+}
+
+.gdfCell, .gdfColHeader {
+ border-bottom: 1px solid #eee;
+ border-right: 1px solid #eee;
+}
+
+
+.ganttLines{
+ position:absolute;
+ width:100%;
+ height:1px;
+ border-top:1px solid #eee;
+ z-index:1;
+}
+
+.gdfCellInput {
+ border: 0 none;
+ font-size: 12px;
+ height: 20px;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ background-color: #d4fbe8;
+}
+
+.gdfCellWrap {
+ border: 0 none;
+ font-size: 12px;
+ height: 17px;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ overflow: hidden;
+
+ background-color: #ffcccc;
+}
+
+.gdfColHeaderOver {
+ opacity: .7;
+}
+
+.gdfHResizing {
+ cursor: w-resize;
+}
+
+.splitterContainer {
+ width: 100%;
+ height: 100%;
+}
+
+.splitBox1, .splitBox2 {
+ overflow-x: scroll;
+ overflow-y: hidden;
+
+ /*background-color: yellow;*/
+}
+
+.splitBox2 {
+ /*background-color: orange;*/
+}
+
+.unselectable {
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+}
+
+.splitElement {
+ outline-style: none;
+ position: absolute;
+ height: 100%;
+}
+
+.vSplitBar {
+ width: 5px;
+ background-color: #aaa;
+ cursor: w-resize;
+ text-align: center;
+ color: white;
+}
+
+.end{
+ border-right:1px dotted #666
+}
+
+.holyH{
+ background-color: #9CB7AA;
+}
+.holy{
+ background-color: #FFF5E6;
+}
+
+
+.expcoll{
+ width:6px;
+ height:6px;
+ margin:1px;
+ padding:1px;
+ background-color:yellow;
+ display:inline-block;
+ border:1px solid gray;
+}
+.expcoll.exp{
+ display:none;
+}
+
+
+.ganttTable{
+ table-layout:fixed;
+}
+
+.ganttTable td,.ganttTable th{
+ overflow: hidden;
+ text-overflow: clip;
+ white-space: nowrap;
+}
+
+.ganttHead1,.ganttHead2{
+ height:20px;
+}
+
+.ganttHead1 th,.ganttHead2 th{
+ border-left:1px solid white;
+}
+
+.ganttToday{
+ position:absolute;
+ top:0;
+ width:1px;
+ height:100%;
+ border-left:2px dotted #13AFA5;
+}
+
+.ganttHighLight{
+ position:absolute;
+ width:100%;
+ height:28px;
+ background-color:yellow;
+ opacity:.4;
+}
+
+.ganttButtonBar{
+ position:relative;
+ padding:5px;
+}
+
+.ganttButtonBar .buttons {
+ float:left; margin:45px 0 0 40px
+}
+
+
+.ganttButtonBar .button span.teamworkIcon{
+ font-size: 150%
+}
+
+.ganttButtonSeparator{
+ border-left:1px solid gray;
+ padding-right:10px;
+ margin-left:10px;
+ font-size: 130%
+}
+
+.ganttLinks{
+ z-index:10;
+}
+
+.taskBox{
+ position:absolute;
+ height:25px;
+ margin-top:3px;
+ z-index:100;
+}
+
+.taskBox .layout {
+ height:100%;
+ color:red;
+ border-radius:2px;
+ background: #eee; /* Old browsers */
+ border:1px solid #bbb;
+}
+
+.taskBox .taskStatus {
+ left:5px;
+ top:10px;
+ position:absolute;
+ width:10px;
+ height:10px;
+}
+
+.taskBox .layout .milestone{
+ top:0px;
+ position:absolute;
+ width:18px;
+ background: url(milestone.png) no-repeat;
+ height:18px;
+ display:none;
+}
+.taskBox .layout .milestone.end{
+ right:0;
+}
+.taskBox .layout .milestone.active{
+ display:block;
+}
+
+.taskBox.hasChild .layout{
+ border-top:2px solid black;
+}
+
+.taskBox .taskProgress{
+ height:5px;
+ position:absolute;
+}
+
+.taskBox .layout.extDep{
+ background-image:url(hasExternalDeps.png);
+}
+
+
+.taskLabel{
+ position:absolute;
+ height:28px;
+ color:black;
+ text-align:right;
+ padding-right:5px;
+ overflow:hidden;
+ left:-200px;
+ width:195px;
+ white-space:nowrap;
+}
+
+
+.taskDepLine {
+ border: 1px solid #9999ff;
+ overflow: hidden;
+ position: absolute;
+}
+
+
+.taskEditRow,.emptyRow {
+ height:30px;
+}
+
+.taskEditRow input{
+ border: 0 none;
+ font-size: 14px;
+ height: 20px;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ font-family: Arial, sans-serif
+}
+
+.taskEditRow.rowSelected td,.taskEditRow.rowSelected input{
+ background-color:#FFFF99;
+}
+
+.taskStatusBox{
+ position:absolute;
+ width:100px;
+ height:24px;
+ border:1px solid #a0a0a0;
+ background-color:#fff;
+ margin-top:2px;
+ margin-left:-1px;
+ padding: 2px
+}
+.taskStatus{
+ width:15px;
+ height:15px;
+ display:inline-block;
+}
+.taskStatus[status=STATUS_ACTIVE]{
+ background-color: #66FF99;
+}
+.taskStatus[status=STATUS_DONE]{
+ background-color: #0099FF;
+}
+.taskStatus[status=STATUS_FAILED]{
+ background-color: #660066;
+}
+.taskStatus[status=STATUS_SUSPENDED]{
+ background-color: #fbb11e;
+}
+.taskStatus[status=STATUS_UNDEFINED]{
+ background-color: #ffffff;
+}
+.taskStatus.selected{
+ border:#666 2px solid;
+}
+
+
+.ui-resizable-helper { border: 1px dotted #00F; }
+.ui-resizable-e, .ui-resizable-w {width: 5px;}
+.ui-draggable{
+ cursor:move;
+}
+
+
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttDrawer.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttDrawer.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttDrawer.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,752 @@
+/*
+ Copyright (c) 2012-2013 Open Lab
+ Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+function Ganttalendar(zoom, startmillis, endMillis, master, minGanttSize) {
+ this.master = master; // is the a GantEditor instance
+ this.element; // is the jquery element containing gantt
+ this.highlightBar;
+ this.zoom = zoom;
+ this.minGanttSize = minGanttSize;
+ this.includeToday=true; //when true today is always visible. If false boundaries comes from tasks periods
+
+ //this.zoomLevels = ["d","w","m","q","s","y"];
+ this.zoomLevels = ["w","m","q","s","y"];
+
+ this.element = this.create(zoom, startmillis, endMillis);
+
+}
+
+Ganttalendar.prototype.zoomGantt = function(isPlus) {
+ var curLevel = this.zoom;
+ var pos = this.zoomLevels.indexOf(curLevel + "");
+
+ var newPos = pos;
+ if (isPlus) {
+ newPos = pos <= 0 ? 0 : pos - 1;
+ } else {
+ newPos = pos >= this.zoomLevels.length - 1 ? this.zoomLevels.length - 1 : pos + 1;
+ }
+ if (newPos != pos) {
+ curLevel = this.zoomLevels[newPos];
+ this.zoom = curLevel;
+ this.refreshGantt();
+ }
+};
+
+
+Ganttalendar.prototype.create = function(zoom, originalStartmillis, originalEndMillis) {
+ //console.debug("Gantt.create " + new Date(originalStartmillis) + " - " + new Date(originalEndMillis));
+
+ var self = this;
+
+ function getPeriod(zoomLevel, stMil, endMillis) {
+ var start = new Date(stMil);
+ var end = new Date(endMillis);
+
+
+ //reset hours
+ if (zoomLevel == "d") {
+ start.setHours(0, 0, 0, 0);
+ end.setHours(23, 59, 59, 999);
+
+ //reset day of week
+ } else if (zoomLevel == "w") {
+ start.setHours(0, 0, 0, 0);
+ end.setHours(23, 59, 59, 999);
+
+ start.setFirstDayOfThisWeek();
+ end.setFirstDayOfThisWeek();
+ end.setDate(end.getDate() + 6);
+
+ //reset day of month
+ } else if (zoomLevel == "m") {
+ start.setHours(0, 0, 0, 0);
+ end.setHours(23, 59, 59, 999);
+
+ start.setDate(1);
+ end.setDate(1);
+ end.setMonth(end.getMonth() + 1);
+ end.setDate(end.getDate() - 1);
+
+ //reset to quarter
+ } else if (zoomLevel == "q") {
+ start.setHours(0, 0, 0, 0);
+ end.setHours(23, 59, 59, 999);
+ start.setDate(1);
+ start.setMonth(Math.floor(start.getMonth() / 3) * 3);
+ end.setDate(1);
+ end.setMonth(Math.floor(end.getMonth() / 3) * 3 + 3);
+ end.setDate(end.getDate() - 1);
+
+ //reset to semester
+ } else if (zoomLevel == "s") {
+ start.setHours(0, 0, 0, 0);
+ end.setHours(23, 59, 59, 999);
+ start.setDate(1);
+
+ start.setMonth(Math.floor(start.getMonth() / 6) * 6);
+ end.setDate(1);
+ end.setMonth(Math.floor(end.getMonth() / 6) * 6 + 6);
+ end.setDate(end.getDate() - 1);
+
+ //reset to year - > gen
+ } else if (zoomLevel == "y") {
+ start.setHours(0, 0, 0, 0);
+ end.setHours(23, 59, 59, 999);
+
+ start.setDate(1);
+ start.setMonth(0);
+
+ end.setDate(1);
+ end.setMonth(12);
+ end.setDate(end.getDate() - 1);
+ }
+ return {start:start.getTime(),end:end.getTime()};
+ }
+
+ function createHeadCell(lbl, span, additionalClass) {
+ var th = $("<th>").html(lbl).attr("colSpan", span);
+ if (additionalClass)
+ th.addClass(additionalClass);
+ return th;
+ }
+
+ function createBodyCell(span, isEnd, additionalClass) {
+ var ret = $("<td>").html(" ").attr("colSpan", span).addClass("ganttBodyCell");
+ if (isEnd)
+ ret.addClass("end");
+ if (additionalClass)
+ ret.addClass(additionalClass);
+ return ret;
+ }
+
+ function createGantt(zoom, startPeriod, endPeriod) {
+ var tr1 = $("<tr>").addClass("ganttHead1");
+ var tr2 = $("<tr>").addClass("ganttHead2");
+ var trBody = $("<tr>").addClass("ganttBody");
+
+ function iterate(renderFunction1, renderFunction2) {
+ var start = new Date(startPeriod);
+ //loop for header1
+ while (start.getTime() <= endPeriod) {
+ renderFunction1(start);
+ }
+
+ //loop for header2
+ start = new Date(startPeriod);
+ while (start.getTime() <= endPeriod) {
+ renderFunction2(start);
+ }
+ }
+
+ //this is computed by hand in order to optimize cell size
+ var computedTableWidth;
+
+ // year
+ if (zoom == "y") {
+ computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24 * 180)) * 100); //180gg = 1 sem = 100px
+ iterate(function(date) {
+ tr1.append(createHeadCell(date.format("yyyy"), 2));
+ date.setFullYear(date.getFullYear() + 1);
+ }, function(date) {
+ var sem = (Math.floor(date.getMonth() / 6) + 1);
+ tr2.append(createHeadCell(GanttMaster.messages["GANT_SEMESTER_SHORT"] + sem, 1));
+ trBody.append(createBodyCell(1, sem == 2));
+ date.setMonth(date.getMonth() + 6);
+ });
+
+ //semester
+ } else if (zoom == "s") {
+ computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24 * 90)) * 100); //90gg = 1 quarter = 100px
+ iterate(function(date) {
+ var end = new Date(date.getTime());
+ end.setMonth(end.getMonth() + 6);
+ end.setDate(end.getDate() - 1);
+ tr1.append(createHeadCell(date.format("MMM") + " - " + end.format("MMM yyyy"), 2));
+ date.setMonth(date.getMonth() + 6);
+ }, function(date) {
+ var quarter = ( Math.floor(date.getMonth() / 3) + 1);
+ tr2.append(createHeadCell(GanttMaster.messages["GANT_QUARTER_SHORT"] + quarter, 1));
+ trBody.append(createBodyCell(1, quarter % 2 == 0));
+ date.setMonth(date.getMonth() + 3);
+ });
+
+ //quarter
+ } else if (zoom == "q") {
+ computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24 * 30)) * 300); //1 month= 300px
+ iterate(function(date) {
+ var end = new Date(date.getTime());
+ end.setMonth(end.getMonth() + 3);
+ end.setDate(end.getDate() - 1);
+ tr1.append(createHeadCell(date.format("MMM") + " - " + end.format("MMM yyyy"), 3));
+ date.setMonth(date.getMonth() + 3);
+ }, function(date) {
+ var lbl = date.format("MMM");
+ tr2.append(createHeadCell(lbl, 1));
+ trBody.append(createBodyCell(1, date.getMonth() % 3 == 2));
+ date.setMonth(date.getMonth() + 1);
+ });
+
+ //month
+ } else if (zoom == "m") {
+ computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24 * 1)) * 20); //1 day= 20px
+ iterate(function(date) {
+ var sm = date.getTime();
+ date.setMonth(date.getMonth() + 1);
+ var daysInMonth = parseInt((date.getTime() - sm) / (3600000 * 24));
+ tr1.append(createHeadCell(new Date(sm).format("MMMM yyyy"), daysInMonth)); //spans mumber of dayn in the month
+ }, function(date) {
+ tr2.append(createHeadCell(date.format("d"), 1, isHoliday(date) ? "holyH" : null));
+ var nd = new Date(date.getTime());
+ nd.setDate(date.getDate() + 1);
+ trBody.append(createBodyCell(1, nd.getDate() == 1, isHoliday(date) ? "holy" : null));
+ date.setDate(date.getDate() + 1);
+ });
+
+ //week
+ } else if (zoom == "w") {
+ computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24)) * 30); //1 day= 30px
+ iterate(function(date) {
+ var end = new Date(date.getTime());
+ end.setDate(end.getDate() + 6);
+ tr1.append(createHeadCell(date.format("MMM d") + " - " + end.format("MMM d'yy"), 7));
+ date.setDate(date.getDate() + 7);
+ }, function(date) {
+ tr2.append(createHeadCell(date.format("EEEE").substr(0, 1), 1, isHoliday(date) ? "holyH" : null));
+ trBody.append(createBodyCell(1, date.getDay() % 7 == (self.master.firstDayOfWeek + 6) % 7, isHoliday(date) ? "holy" : null));
+ date.setDate(date.getDate() + 1);
+ });
+
+ //days
+ } else if (zoom == "d") {
+ computedTableWidth = Math.floor(((endPeriod - startPeriod) / (3600000 * 24)) * 200); //1 day= 200px
+ iterate(function(date) {
+ tr1.append(createHeadCell(date.format("EEEE d MMMM yyyy"), 4, isHoliday(date) ? "holyH" : null));
+ date.setDate(date.getDate() + 1);
+ }, function(date) {
+ tr2.append(createHeadCell(date.format("HH"), 1, isHoliday(date) ? "holyH" : null));
+ trBody.append(createBodyCell(1, date.getHours() > 17, isHoliday(date) ? "holy" : null));
+ date.setHours(date.getHours() + 6);
+ });
+
+ } else {
+ console.error("Wrong level " + zoom);
+ }
+
+ //set a minimal width
+ computedTableWidth = Math.max(computedTableWidth, self.minGanttSize);
+
+ var table = $("<table cellspacing=0 cellpadding=0>");
+ table.append(tr1).append(tr2).append(trBody).addClass("ganttTable").css({width:computedTableWidth});
+ table.height(self.master.editor.element.height());
+
+ var box = $("<div>");
+ box.addClass("gantt unselectable").attr("unselectable","true").css({position:"relative",width:computedTableWidth});
+ box.append(table);
+
+ //highlightBar
+ var hlb = $("<div>").addClass("ganttHighLight");
+ box.append(hlb);
+ self.highlightBar = hlb;
+
+ //create link container
+ var links = $("<div>");
+ links.addClass("ganttLinks").css({position:"absolute",top:0,width:computedTableWidth,height:"100%"});
+ box.append(links);
+
+
+ //compute scalefactor fx
+ self.fx = computedTableWidth / (endPeriod - startPeriod);
+
+ // drawTodayLine
+ if (new Date().getTime() > self.startMillis && new Date().getTime() < self.endMillis) {
+ var x = Math.round(((new Date().getTime()) - self.startMillis) * self.fx);
+ var today = $("<div>").addClass("ganttToday").css("left", x);
+ box.append(today);
+ }
+
+ return box;
+ }
+
+ //if include today synch extremes
+ if (this.includeToday){
+ var today=new Date().getTime();
+ originalStartmillis=originalStartmillis>today ? today:originalStartmillis;
+ originalEndMillis=originalEndMillis<today ? today:originalEndMillis;
+ }
+
+
+ //get best dimension fo gantt
+ var period = getPeriod(zoom, originalStartmillis, originalEndMillis); //this is enlarged to match complete periods basing on zoom level
+
+ //console.debug(new Date(period.start) + " " + new Date(period.end));
+ self.startMillis = period.start; //real dimension of gantt
+ self.endMillis = period.end;
+ self.originalStartMillis = originalStartmillis; //minimal dimension required by user or by task duration
+ self.originalEndMillis = originalEndMillis;
+
+ var table = createGantt(zoom, period.start, period.end);
+
+ return table;
+};
+
+
+//<%-------------------------------------- GANT TASK GRAPHIC ELEMENT --------------------------------------%>
+Ganttalendar.prototype.drawTask = function (task) {
+ //console.debug("drawTask", task.name,new Date(task.start));
+ var self = this;
+ //var prof = new Profiler("ganttDrawTask");
+ //var editorRow = self.master.editor.element.find("tr[taskId=" + task.id + "]");
+ editorRow = task.rowElement;
+ var top = editorRow.position().top+self.master.editor.element.parent().scrollTop();
+ var x = Math.round((task.start - self.startMillis) * self.fx);
+ var taskBox = $.JST.createFromTemplate(task, "TASKBAR");
+
+
+
+ //save row element on task
+ task.ganttElement = taskBox;
+
+ //if I'm parent
+ if (task.isParent())
+ taskBox.addClass("hasChild");
+
+
+ taskBox.css({top:top,left:x,width:Math.round((task.end - task.start) * self.fx)});
+
+ if (this.master.canWrite) {
+ taskBox.resizable({
+ handles: 'e' + ( task.depends ? "" : ",w"), //if depends cannot move start
+ //helper: "ui-resizable-helper",
+ //grid:[oneDaySize,oneDaySize],
+
+ resize:function(event, ui) {
+ //console.debug(ui)
+ $(".taskLabel[taskId=" + ui.helper.attr("taskId") + "]").css("width", ui.position.left);
+ event.stopImmediatePropagation();
+ event.stopPropagation();
+ },
+ stop:function(event, ui) {
+ //console.debug(ui)
+ var task = self.master.getTask(ui.element.attr("taskId"));
+ var s = Math.round((ui.position.left / self.fx) + self.startMillis);
+ var e = Math.round(((ui.position.left + ui.size.width) / self.fx) + self.startMillis);
+
+ self.master.beginTransaction();
+ self.master.changeTaskDates(task, new Date(s), new Date(e));
+ self.master.endTransaction();
+ }
+
+ });
+
+ }
+
+ taskBox.dblclick(function() {
+ self.master.showTaskEditor($(this).closest("[taskId]").attr("taskId"));
+
+ }).mousedown(function() {
+ var task = self.master.getTask($(this).attr("taskId"));
+ task.rowElement.click();
+ });
+
+ //panning only in no depends
+ if (!task.depends && this.master.canWrite) {
+
+ taskBox.css("position", "absolute").draggable({
+ axis:'x',
+ drag:function (event, ui) {
+ $(".taskLabel[taskId=" + $(this).attr("taskId") + "]").css("width", ui.position.left);
+ },
+ stop:function(event, ui) {
+ //console.debug(ui,$(this))
+ var task = self.master.getTask($(this).attr("taskId"));
+ var s = Math.round((ui.position.left / self.fx) + self.startMillis);
+
+ self.master.beginTransaction();
+ self.master.moveTask(task, new Date(s));
+ self.master.endTransaction();
+ }/*,
+ start:function(event, ui) {
+ var task = self.master.getTask($(this).attr("taskId"));
+ var s = Math.round((ui.position.left / self.fx) + self.startMillis);
+ console.debug("start",new Date(s));
+ }*/
+ });
+ }
+
+
+ var taskBoxSeparator=$("<div class='ganttLines'></div>");
+ taskBoxSeparator.css({top:top+taskBoxSeparator.height()});
+// taskBoxSeparator.css({top:top+18});
+
+
+ self.element.append(taskBox);
+ self.element.append(taskBoxSeparator);
+
+ //ask for redraw link
+ self.redrawLinks();
+
+ //prof.stop();
+};
+
+
+Ganttalendar.prototype.addTask = function (task) {
+ //set new boundaries for gantt
+ this.originalEndMillis = this.originalEndMillis > task.end ? this.originalEndMillis : task.end;
+ this.originalStartMillis = this.originalStartMillis < task.start ? this.originalStartMillis : task.start;
+};
+
+
+//<%-------------------------------------- GANT DRAW LINK ELEMENT --------------------------------------%>
+//'from' and 'to' are tasks already drawn
+Ganttalendar.prototype.drawLink = function (from, to, type) {
+ var peduncolusSize = 10;
+ var lineSize = 2;
+
+ /**
+ * A representation of a Horizontal line
+ */
+ HLine = function(width, top, left) {
+ var hl = $("<div>").addClass("taskDepLine");
+ hl.css({
+ height: lineSize,
+ left: left,
+ width: width,
+ top: top - lineSize / 2
+ });
+ return hl;
+ };
+
+ /**
+ * A representation of a Vertical line
+ */
+ VLine = function(height, top, left) {
+ var vl = $("<div>").addClass("taskDepLine");
+ vl.css({
+ height: height,
+ left:left - lineSize / 2,
+ width: lineSize,
+ top: top
+ });
+ return vl;
+ };
+
+ /**
+ * Given an item, extract its rendered position
+ * width and height into a structure.
+ */
+ function buildRect(item) {
+ var rect = item.ganttElement.position();
+ rect.width = item.ganttElement.width();
+ rect.height = item.ganttElement.height();
+
+ return rect;
+ }
+
+ /**
+ * The default rendering method, which paints a start to end dependency.
+ *
+ * @see buildRect
+ */
+ function drawStartToEnd(rectFrom, rectTo, peduncolusSize) {
+ var left, top;
+
+ var ndo = $("<div>").attr({
+ from: from.id,
+ to: to.id
+ });
+
+ var currentX = rectFrom.left + rectFrom.width;
+ var currentY = rectFrom.height / 2 + rectFrom.top;
+
+ var useThreeLine = (currentX + 2 * peduncolusSize) < rectTo.left;
+
+ if (!useThreeLine) {
+ // L1
+ if (peduncolusSize > 0) {
+ var l1 = new HLine(peduncolusSize, currentY, currentX);
+ currentX = currentX + peduncolusSize;
+ ndo.append(l1);
+ }
+
+ // L2
+ var l2_4size = ((rectTo.top + rectTo.height / 2) - (rectFrom.top + rectFrom.height / 2)) / 2;
+ var l2;
+ if (l2_4size < 0) {
+ l2 = new VLine(-l2_4size, currentY + l2_4size, currentX);
+ } else {
+ l2 = new VLine(l2_4size, currentY, currentX);
+ }
+ currentY = currentY + l2_4size;
+
+ ndo.append(l2);
+
+ // L3
+ var l3size = rectFrom.left + rectFrom.width + peduncolusSize - (rectTo.left - peduncolusSize);
+ currentX = currentX - l3size;
+ var l3 = new HLine(l3size, currentY, currentX);
+ ndo.append(l3);
+
+ // L4
+ var l4;
+ if (l2_4size < 0) {
+ l4 = new VLine(-l2_4size, currentY + l2_4size, currentX);
+ } else {
+ l4 = new VLine(l2_4size, currentY, currentX);
+ }
+ ndo.append(l4);
+
+ currentY = currentY + l2_4size;
+
+ // L5
+ if (peduncolusSize > 0) {
+ var l5 = new HLine(peduncolusSize, currentY, currentX);
+ currentX = currentX + peduncolusSize;
+ ndo.append(l5);
+
+ }
+ } else {
+ //L1
+ var l1_3Size = (rectTo.left - currentX) / 2;
+ var l1 = new HLine(l1_3Size, currentY, currentX);
+ currentX = currentX + l1_3Size;
+ ndo.append(l1);
+
+ //L2
+ var l2Size = ((rectTo.top + rectTo.height / 2) - (rectFrom.top + rectFrom.height / 2));
+ var l2;
+ if (l2Size < 0) {
+ l2 = new VLine(-l2Size, currentY + l2Size, currentX);
+ } else {
+ l2 = new VLine(l2Size, currentY, currentX);
+ }
+ ndo.append(l2);
+
+ currentY = currentY + l2Size;
+
+ //L3
+ var l3 = new HLine(l1_3Size, currentY, currentX);
+ currentX = currentX + l1_3Size;
+ ndo.append(l3);
+ }
+
+ //arrow
+ var arr = $("<img src='linkArrow.png'>").css({
+ position: 'absolute',
+ top: rectTo.top + rectTo.height / 2 - 5,
+ left: rectTo.left - 5
+ });
+
+ ndo.append(arr);
+
+ return ndo;
+ }
+
+ /**
+ * A rendering method which paints a start to start dependency.
+ *
+ * @see buildRect
+ */
+ function drawStartToStart(rectFrom, rectTo, peduncolusSize) {
+ var left, top;
+
+ var ndo = $("<div>").attr({
+ from: from.id,
+ to: to.id
+ });
+
+ var currentX = rectFrom.left;
+ var currentY = rectFrom.height / 2 + rectFrom.top;
+
+ var useThreeLine = (currentX + 2 * peduncolusSize) < rectTo.left;
+
+ if (!useThreeLine) {
+ // L1
+ if (peduncolusSize > 0) {
+ var l1 = new HLine(peduncolusSize, currentY, currentX - peduncolusSize);
+ currentX = currentX - peduncolusSize;
+ ndo.append(l1);
+ }
+
+ // L2
+ var l2_4size = ((rectTo.top + rectTo.height / 2) - (rectFrom.top + rectFrom.height / 2)) / 2;
+ var l2;
+ if (l2_4size < 0) {
+ l2 = new VLine(-l2_4size, currentY + l2_4size, currentX);
+ } else {
+ l2 = new VLine(l2_4size, currentY, currentX);
+ }
+ currentY = currentY + l2_4size;
+
+ ndo.append(l2);
+
+ // L3
+ var l3size = (rectFrom.left - peduncolusSize) - (rectTo.left - peduncolusSize);
+ currentX = currentX - l3size;
+ var l3 = new HLine(l3size, currentY, currentX);
+ ndo.append(l3);
+
+ // L4
+ var l4;
+ if (l2_4size < 0) {
+ l4 = new VLine(-l2_4size, currentY + l2_4size, currentX);
+ } else {
+ l4 = new VLine(l2_4size, currentY, currentX);
+ }
+ ndo.append(l4);
+
+ currentY = currentY + l2_4size;
+
+ // L5
+ if (peduncolusSize > 0) {
+ var l5 = new HLine(peduncolusSize, currentY, currentX);
+ currentX = currentX + peduncolusSize;
+ ndo.append(l5);
+ }
+ } else {
+ //L1
+
+ var l1 = new HLine(peduncolusSize, currentY, currentX - peduncolusSize);
+ currentX = currentX - peduncolusSize;
+ ndo.append(l1);
+
+ //L2
+ var l2Size = ((rectTo.top + rectTo.height / 2) - (rectFrom.top + rectFrom.height / 2));
+ var l2;
+ if (l2Size < 0) {
+ l2 = new VLine(-l2Size, currentY + l2Size, currentX);
+ } else {
+ l2 = new VLine(l2Size, currentY, currentX);
+ }
+ ndo.append(l2);
+
+ currentY = currentY + l2Size;
+
+ //L3
+
+ var l3 = new HLine(peduncolusSize + (rectTo.left - rectFrom.left), currentY, currentX);
+ currentX = currentX + peduncolusSize + (rectTo.left - rectFrom.left);
+ ndo.append(l3);
+ }
+
+ //arrow
+ var arr = $("<img src='linkArrow.png'>").css({
+ position: 'absolute',
+ top: rectTo.top + rectTo.height / 2 - 5,
+ left: rectTo.left - 5
+ });
+
+ ndo.append(arr);
+
+ return ndo;
+ }
+
+ var rectFrom = buildRect(from);
+ var rectTo = buildRect(to);
+
+ // Dispatch to the correct renderer
+ if (type == 'start-to-start') {
+ this.element.find(".ganttLinks").append(
+ drawStartToStart(rectFrom, rectTo, peduncolusSize)
+ );
+ } else {
+ this.element.find(".ganttLinks").append(
+ drawStartToEnd(rectFrom, rectTo, peduncolusSize)
+ );
+ }
+};
+
+
+Ganttalendar.prototype.redrawLinks = function() {
+ //console.debug("redrawLinks ");
+ var self = this;
+ this.element.stopTime("ganttlnksredr");
+ this.element.oneTime(60, "ganttlnksredr", function() {
+ //var prof=new Profiler("gd_drawLink_real");
+ self.element.find(".ganttLinks").empty();
+ for (var i=0;i<self.master.links.length;i++) {
+ var link = self.master.links[i];
+ self.drawLink(link.from, link.to);
+ }
+ //prof.stop();
+ });
+};
+
+
+Ganttalendar.prototype.reset = function() {
+ this.element.find(".ganttLinks").empty();
+ this.element.find("[taskId]").remove();
+};
+
+
+Ganttalendar.prototype.redrawTasks = function() {
+ for (var i=0;i<this.master.tasks.length;i++) {
+ var task = this.master.tasks[i];
+ this.drawTask(task);
+ }
+};
+
+
+Ganttalendar.prototype.refreshGantt = function() {
+ //console.debug("refreshGantt")
+ var par = this.element.parent();
+
+ //try to maintain last scroll
+ var scrollY=par.scrollTop();
+ var scrollX=par.scrollLeft();
+
+ this.element.remove();
+ //guess the zoom level in base of period
+ if (!this.zoom ){
+ var days = (this.originalEndMillis - this.originalStartMillis) / (3600000 * 24);
+ this.zoom = this.zoomLevels[days < 2 ? 0 : (days < 15 ? 1 : (days < 60 ? 2 : (days < 150 ? 3 : (days < 400 ? 4 : 5 ) ) ) )];
+ }
+ var domEl = this.create(this.zoom, this.originalStartMillis, this.originalEndMillis);
+ this.element = domEl;
+ par.append(domEl);
+ this.redrawTasks();
+
+ //set old scroll
+ //console.debug("old scroll:",scrollX,scrollY)
+ par.scrollTop(scrollY);
+ par.scrollLeft(scrollX);
+
+ //set current task
+ if (this.master.currentTask) {
+ this.highlightBar.css("top", this.master.currentTask.ganttElement.position().top);
+ }
+};
+
+
+Ganttalendar.prototype.fitGantt = function() {
+ delete this.zoom;
+ this.refreshGantt();
+};
+
+Ganttalendar.prototype.centerOnToday = function() {
+ //console.debug("centerOnToday");
+ var x = Math.round(((new Date().getTime()) - this.startMillis) * this.fx);
+ this.element.parent().scrollLeft(x);
+};
+
+
+
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttGridEditor.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttGridEditor.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttGridEditor.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,518 @@
+/*
+ Copyright (c) 2012-2013 Open Lab
+ Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+function GridEditor(master) {
+ this.master = master; // is the a GantEditor instance
+ var gridEditor = $.JST.createFromTemplate({}, "TASKSEDITHEAD");
+ gridEditor.gridify();
+ this.element = gridEditor;
+}
+
+
+GridEditor.prototype.fillEmptyLines = function() {
+ var factory = new TaskFactory();
+
+ //console.debug("GridEditor.fillEmptyLines");
+ var rowsToAdd = 30 - this.element.find(".taskEditRow").size();
+
+ //fill with empty lines
+ for (var i = 0; i < rowsToAdd; i++) {
+ var emptyRow = $.JST.createFromTemplate({}, "TASKEMPTYROW");
+ //click on empty row create a task and fill above
+ var master = this.master;
+ emptyRow.click(function(ev) {
+ master.beginTransaction();
+ var emptyRow = $(this);
+ var lastTask;
+ var start = new Date().getTime();
+ var level = 0;
+ if (master.tasks[0]) {
+ start = master.tasks[0].start;
+ level = master.tasks[0].level + 1;
+ }
+
+ //fill all empty previouses
+ emptyRow.prevAll(".emptyRow").andSelf().each(function() {
+ var ch = factory.build("tmp_fk" + new Date().getTime(), "", "", level, start, 1);
+ var task = master.addTask(ch);
+ lastTask = ch;
+ });
+ master.endTransaction();
+ lastTask.rowElement.click();
+ lastTask.rowElement.find("[name=name]").focus()//focus to "name" input
+ .blur(function() { //if name not inserted -> undo -> remove just added lines
+ var imp = $(this);
+ if (!imp.isValueChanged())
+ master.undo();
+ });
+ });
+ this.element.append(emptyRow);
+ }
+};
+
+
+GridEditor.prototype.addTask = function(task, row) {
+ //console.debug("GridEditor.addTask",task,row);
+ //var prof = new Profiler("editorAddTaskHtml");
+
+ //remove extisting row
+ this.element.find("[taskId=" + task.id + "]").remove();
+
+ var taskRow = $.JST.createFromTemplate(task, "TASKROW");
+ //save row element on task
+ task.rowElement = taskRow;
+
+ this.bindRowEvents(task, taskRow);
+
+ if (typeof(row) != "number") {
+ var emptyRow = this.element.find(".emptyRow:first"); //tries to fill an empty row
+ if (emptyRow.size() > 0)
+ emptyRow.replaceWith(taskRow);
+ else
+ this.element.append(taskRow);
+ } else {
+ var tr = this.element.find("tr.taskEditRow").eq(row);
+ if (tr.size() > 0) {
+ tr.before(taskRow);
+ } else {
+ this.element.append(taskRow);
+ }
+
+ }
+ this.element.find(".taskRowIndex").each(function(i, el) {
+ $(el).html(i + 1);
+ });
+ //prof.stop();
+
+ return taskRow;
+};
+
+
+GridEditor.prototype.refreshTaskRow = function(task) {
+ //console.debug("refreshTaskRow")
+ //var profiler = new Profiler("editorRefreshTaskRow");
+ var row = task.rowElement;
+
+ row.find(".taskRowIndex").html(task.getRow() + 1);
+ row.find(".indentCell").css("padding-left", task.level * 10);
+ row.find("[name=name]").val(task.name);
+ row.find("[name=code]").val(task.code);
+ row.find("[status]").attr("status", task.status);
+
+ row.find("[name=duration]").val(task.duration);
+ row.find("[name=start]").val(new Date(task.start).format()).updateOldValue(); // called on dates only because for other field is called on focus event
+ row.find("[name=end]").val(new Date(task.end).format()).updateOldValue();
+ row.find("[name=depends]").val(task.depends);
+ row.find(".taskAssigs").html(task.getAssigsString());
+
+ //profiler.stop();
+};
+
+GridEditor.prototype.redraw = function() {
+ for (var i = 0; i < this.master.tasks.length; i++) {
+ this.refreshTaskRow(this.master.tasks[i]);
+ }
+};
+
+GridEditor.prototype.reset = function() {
+ this.element.find("[taskId]").remove();
+};
+
+
+GridEditor.prototype.bindRowEvents = function (task, taskRow) {
+ var self = this;
+ //console.debug("bindRowEvents",this,this.master,this.master.canWrite);
+ if (this.master.canWrite) {
+ self.bindRowInputEvents(task,taskRow);
+
+ } else { //cannot write: disable input
+ taskRow.find("input").attr("readonly", true);
+ }
+
+ taskRow.find(".edit").click(function() {self.openFullEditor(task,taskRow)});
+
+};
+
+
+GridEditor.prototype.bindRowInputEvents = function (task, taskRow) {
+ var self = this;
+
+ //bind dateField on dates
+ taskRow.find(".date").each(function () {
+ var el = $(this);
+
+ el.click(function () {
+ var inp = $(this);
+ inp.dateField({
+ inputField:el
+ });
+ });
+
+ el.blur(function (date) {
+ var inp = $(this);
+ if (inp.isValueChanged()) {
+ if (!Date.isValid(inp.val())) {
+ alert(GanttMaster.messages["INVALID_DATE_FORMAT"]);
+ inp.val(inp.getOldValue());
+
+ } else {
+ var date = Date.parseString(inp.val());
+ var row = inp.closest("tr");
+ var taskId = row.attr("taskId");
+ var task = self.master.getTask(taskId);
+ var lstart = task.start;
+ var lend = task.end;
+
+ if (inp.attr("name") == "start") {
+ lstart = date.getTime();
+ if (lstart >= lend) {
+ var end_as_date = new Date(lstart);
+ lend = end_as_date.add('d', task.duration).getTime();
+ }
+
+ //update task from editor
+ self.master.beginTransaction();
+ self.master.moveTask(task, lstart);
+ self.master.endTransaction();
+
+ } else {
+ var end_as_date = new Date(date.getTime());
+ lend = end_as_date.getTime();
+ if (lstart >= lend) {
+ end_as_date.add('d', -1 * task.duration);
+ lstart = end_as_date.getTime();
+ }
+
+ //update task from editor
+ self.master.beginTransaction();
+ self.master.changeTaskDates(task, lstart, lend);
+ self.master.endTransaction();
+ }
+
+
+ inp.updateOldValue(); //in order to avoid multiple call if nothing changed
+ }
+ }
+ });
+ });
+
+
+ //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)
+ taskRow.find("input:not(.date)").focus(function () {
+ $(this).updateOldValue();
+
+ }).blur(function () {
+ var el = $(this);
+ if (el.isValueChanged()) {
+ var row = el.closest("tr");
+ var taskId = row.attr("taskId");
+
+ var task = self.master.getTask(taskId);
+
+ //update task from editor
+ var field = el.attr("name");
+
+ self.master.beginTransaction();
+
+ if (field == "depends") {
+
+ var oldDeps = task.depends;
+ task.depends = el.val();
+ // update links
+ var linkOK = self.master.updateLinks(task);
+ if (linkOK) {
+ //synchronize status fro superiors states
+ var sups = task.getSuperiors();
+ for (var i = 0; i < sups.length; i++) {
+ if (!sups[i].from.synchronizeStatus())
+ break;
+ }
+
+ self.master.changeTaskDates(task, task.start, task.end);
+ }
+
+ } else if (field == "duration") {
+ var dur = task.duration;
+ dur = parseInt(el.val()) || 1;
+ el.val(dur);
+ var newEnd = computeEndByDuration(task.start, dur);
+ self.master.changeTaskDates(task, task.start, newEnd);
+
+ } else {
+ task[field] = el.val();
+ }
+ self.master.endTransaction();
+ }
+ });
+
+
+ //change status
+ taskRow.find(".taskStatus").click(function () {
+ var el = $(this);
+ var tr = el.closest("[taskId]");
+ var taskId = tr.attr("taskId");
+ var task = self.master.getTask(taskId);
+
+ var changer = $.JST.createFromTemplate({}, "CHANGE_STATUS");
+ changer.css("top", tr.position().top + self.element.parent().scrollTop());
+ changer.find("[status=" + task.status + "]").addClass("selected");
+ changer.find(".taskStatus").click(function () {
+ self.master.beginTransaction();
+ task.changeStatus($(this).attr("status"));
+ self.master.endTransaction();
+ el.attr("status", task.status);
+ changer.remove();
+ el.show();
+
+ });
+ el.hide().oneTime(3000, "hideChanger", function () {
+ changer.remove();
+ $(this).show();
+ });
+ el.after(changer);
+ });
+
+
+ /*//expand collapse todo to be completed
+ taskRow.find(".expcoll").click(function(){
+ //expand?
+ var el=$(this);
+ var taskId=el.closest("[taskId]").attr("taskId");
+ var task=self.master.getTask(taskId);
+ var descs=task.getDescendant();
+ if (el.is(".exp")){
+ for (var i=0;i<descs.length;i++)
+ descs[i].rowElement.show();
+ } else {
+ for (var i=0;i<descs.length;i++)
+ descs[i].rowElement.hide();
+ }
+
+ });*/
+
+ //bind row selection
+ taskRow.click(function () {
+ var row = $(this);
+ //var isSel = row.hasClass("rowSelected");
+ row.closest("table").find(".rowSelected").removeClass("rowSelected");
+ row.addClass("rowSelected");
+
+ //set current task
+ self.master.currentTask = self.master.getTask(row.attr("taskId"));
+
+ //move highlighter
+ if (self.master.currentTask.ganttElement)
+ self.master.gantt.highlightBar.css("top", self.master.currentTask.ganttElement.position().top);
+
+ //if offscreen scroll to element
+ var top = row.position().top;
+ if (row.position().top > self.element.parent().height()) {
+ self.master.gantt.element.parent().scrollTop(row.position().top - self.element.parent().height() + 100);
+ }
+ });
+
+};
+
+
+
+GridEditor.prototype.openFullEditor = function (task, taskRow) {
+
+ var self=this;
+
+ //task editor in popup
+ var taskId = taskRow.attr("taskId");
+ //console.debug(task);
+
+ //make task editor
+ var taskEditor = $.JST.createFromTemplate({}, "TASK_EDITOR");
+
+ taskEditor.find("#name").val(task.name);
+ taskEditor.find("#description").val(task.description);
+ taskEditor.find("#code").val(task.code);
+ taskEditor.find("#progress").val(task.progress ? parseFloat(task.progress) : 0);
+ taskEditor.find("#status").attr("status", task.status);
+
+ if (task.startIsMilestone)
+ taskEditor.find("#startIsMilestone").attr("checked", true);
+ if (task.endIsMilestone)
+ taskEditor.find("#endIsMilestone").attr("checked", true);
+
+ taskEditor.find("#duration").val(task.duration);
+ taskEditor.find("#start").val(new Date(task.start).format());
+ taskEditor.find("#end").val(new Date(task.end).format());
+
+ //taskEditor.find("[name=depends]").val(task.depends);
+
+ //make assignments table
+ var assigsTable = taskEditor.find("#assigsTable");
+ assigsTable.find("[assigId]").remove();
+ // loop on already assigned resources
+ for (var i = 0; i < task.assigs.length; i++) {
+ var assig = task.assigs[i];
+ var assigRow = $.JST.createFromTemplate({task:task, assig:assig}, "ASSIGNMENT_ROW");
+ assigsTable.append(assigRow);
+ }
+
+ if (!self.master.canWrite) {
+ taskEditor.find("input,textarea").attr("readOnly", true);
+ taskEditor.find("input:checkbox,select").attr("disabled", true);
+ } else {
+
+ //bind dateField on dates
+ taskEditor.find("#start").click(function () {
+ $(this).dateField({
+ inputField:$(this),
+ callback: function (date) {
+ var dur = parseInt(taskEditor.find("#duration").val());
+ date.clearTime();
+ taskEditor.find("#end").val(new Date(computeEndByDuration(date.getTime(), dur)).format());
+ }
+ });
+ });
+
+ //bind dateField on dates
+ taskEditor.find("#end").click(function () {
+ $(this).dateField({
+ inputField:$(this),
+ callback: function (end) {
+ var start = Date.parseString(taskEditor.find("#start").val());
+ end.setHours(23, 59, 59, 999);
+
+ if (end.getTime() < start.getTime()) {
+ var dur = parseInt(taskEditor.find("#duration").val());
+ start = incrementDateByWorkingDays(end.getTime(), -dur);
+ taskEditor.find("#start").val(new Date(computeStart(start)).format());
+ } else {
+ taskEditor.find("#duration").val(recomputeDuration(start.getTime(), end.getTime()));
+ }
+ }
+ });
+ });
+
+ //bind blur on duration
+ taskEditor.find("#duration").change(function () {
+ var start = Date.parseString(taskEditor.find("#start").val());
+ var el = $(this);
+ var dur = parseInt(el.val());
+ dur = dur <= 0 ? 1 : dur;
+ el.val(dur);
+ taskEditor.find("#end").val(new Date(computeEndByDuration(start.getTime(), dur)).format());
+ });
+
+ //bind add assignment
+ taskEditor.find("#addAssig").click(function () {
+ var assigsTable = taskEditor.find("#assigsTable");
+ var assigRow = $.JST.createFromTemplate({task:task, assig:{id:"tmp_" + new Date().getTime()}}, "ASSIGNMENT_ROW");
+ assigsTable.append(assigRow);
+ });
+
+ taskEditor.find("#status").click(function () {
+ var tskStatusChooser = $(this);
+ var changer = $.JST.createFromTemplate({}, "CHANGE_STATUS");
+ changer.css("top", tskStatusChooser.position().top);
+ changer.find("[status=" + task.status + "]").addClass("selected");
+ changer.find(".taskStatus").click(function () {
+ tskStatusChooser.attr("status", $(this).attr("status"));
+ changer.remove();
+ tskStatusChooser.show();
+ });
+ tskStatusChooser.hide().oneTime(3000, "hideChanger", function () {
+ changer.remove();
+ $(this).show();
+ });
+ tskStatusChooser.after(changer);
+ });
+
+ //save task
+ taskEditor.find("#saveButton").click(function () {
+ var task = self.master.getTask(taskId); // get task again because in case of rollback old task is lost
+
+ self.master.beginTransaction();
+ task.name = taskEditor.find("#name").val();
+ task.description = taskEditor.find("#description").val();
+ task.code = taskEditor.find("#code").val();
+ task.progress = parseFloat(taskEditor.find("#progress").val());
+ task.duration = parseInt(taskEditor.find("#duration").val());
+ task.startIsMilestone = taskEditor.find("#startIsMilestone").is(":checked");
+ task.endIsMilestone = taskEditor.find("#endIsMilestone").is(":checked");
+
+ //set assignments
+ taskEditor.find("tr[assigId]").each(function () {
+ var trAss = $(this);
+ var assId = trAss.attr("assigId");
+ var resId = trAss.find("[name=resourceId]").val();
+ var roleId = trAss.find("[name=roleId]").val();
+ var effort = millisFromString(trAss.find("[name=effort]").val());
+
+
+ //check if an existing assig has been deleted and re-created with the same values
+ var found = false;
+ for (var i = 0; i < task.assigs.length; i++) {
+ var ass = task.assigs[i];
+
+ if (assId == ass.id) {
+ ass.effort = effort;
+ ass.roleId = roleId;
+ ass.resourceId = resId;
+ ass.touched = true;
+ found = true;
+ break;
+
+ } else if (roleId == ass.roleId && resId == ass.resourceId) {
+ ass.effort = effort;
+ ass.touched = true;
+ found = true;
+ break;
+
+ }
+ }
+
+ if (!found) { //insert
+ var ass = task.createAssignment("tmp_" + new Date().getTime(), resId, roleId, effort);
+ ass.touched = true;
+ }
+
+ });
+
+ //remove untouched assigs
+ task.assigs = task.assigs.filter(function (ass) {
+ var ret = ass.touched;
+ delete ass.touched;
+ return ret;
+ });
+
+ //change dates
+ task.setPeriod(Date.parseString(taskEditor.find("#start").val()).getTime(), Date.parseString(taskEditor.find("#end").val()).getTime() + (3600000 * 24));
+
+ //change status
+ task.changeStatus(taskEditor.find("#status").attr("status"));
+
+ if (self.master.endTransaction()) {
+ $("#__blackpopup__").trigger("close");
+ }
+
+ });
+ }
+
+ var ndo = createBlackPage(800, 500).append(taskEditor);
+
+};
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttMaster.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttMaster.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttMaster.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,702 @@
+/*
+ Copyright (c) 2012-2013 Open Lab
+ Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+function GanttMaster() {
+ this.tasks = [];
+ this.deletedTaskIds=[];
+ this.links = [];
+
+ this.editor; //element for editor
+ this.gantt; //element for gantt
+
+ this.element;
+
+
+ this.resources; //list of resources
+ this.roles; //list of roles
+
+ this.minEditableDate = 0;
+ this.maxEditableDate = Infinity;
+
+ this.canWriteOnParent=true;
+ this.canWrite=true;
+
+ this.firstDayOfWeek = Date.firstDayOfWeek;
+
+ this.currentTask; // task currently selected;
+
+ this.__currentTransaction; // a transaction object holds previous state during changes
+ this.__undoStack = [];
+ this.__redoStack = [];
+
+ var self = this;
+}
+
+GanttMaster.prototype.init = function(place) {
+ this.element = place;
+
+ var self=this;
+
+ //load templates
+ $("#gantEditorTemplates").loadTemplates().remove(); // TODO: Remove inline jquery, this should be injected
+
+ //create editor
+ this.editor = new GridEditor(this);
+ this.editor.element.width(place.width() * .9 - 10);
+ place.append(this.editor.element);
+
+ //create gantt
+ this.gantt = new Ganttalendar("m", new Date().getTime() - 3600000 * 24 * 2, new Date().getTime() + 3600000 * 24 * 15, this, place.width() * .6);
+
+ //setup splitter
+ var splitter = $.splittify.init(place, this.editor.element, this.gantt.element, 70);
+ splitter.secondBox.css("overflow-y", "auto").scroll(function() {
+ splitter.firstBox.scrollTop(splitter.secondBox.scrollTop());
+ });
+
+
+ //prepend buttons
+ place.before($.JST.createFromTemplate({}, "GANTBUTTONS"));
+
+
+ //bindings
+ place.bind("refreshTasks.gantt", function() {
+ self.redrawTasks();
+ }).bind("refreshTask.gantt", function(e, task) {
+ self.drawTask(task);
+
+ }).bind("deleteCurrentTask.gantt", function(e) {
+ var row = self.currentTask.getRow();
+ if (self.currentTask && (row>0 || self.currentTask.isNew())) {
+ self.beginTransaction();
+
+ self.currentTask.deleteTask();
+
+ self.currentTask = undefined;
+ //recompute depends string
+ self.updateDependsStrings();
+
+ //redraw
+ self.redraw();
+
+ //focus next row
+ row = row > self.tasks.length - 1 ? self.tasks.length - 1 : row;
+ if (row >= 0) {
+ self.currentTask = self.tasks[row];
+ self.currentTask.rowElement.click();
+ self.currentTask.rowElement.find("[name=name]").focus();
+ }
+ self.endTransaction();
+ }
+
+
+ }).bind("addAboveCurrentTask.gantt", function() {
+ var factory = new TaskFactory();
+
+ var ch;
+ var row = 0;
+ if (self.currentTask) {
+ //cannot add brothers to root
+ if (self.currentTask.level<=0)
+ return;
+
+ ch = factory.build("tmp_" + new Date().getTime(), "", "", self.currentTask.level, self.currentTask.start, 1);
+ row = self.currentTask.getRow();
+ } else {
+ ch = factory.build("tmp_" + new Date().getTime(), "", "", 0, new Date().getTime(), 1);
+ }
+ self.beginTransaction();
+ var task = self.addTask(ch, row);
+ if (task) {
+ task.rowElement.click();
+ task.rowElement.find("[name=name]").focus();
+ }
+ self.endTransaction();
+
+ }).bind("addBelowCurrentTask.gantt", function() {
+ var factory = new TaskFactory();
+ self.beginTransaction();
+ var ch;
+ var row = 0;
+ if (self.currentTask) {
+ ch = factory.build("tmp_" + new Date().getTime(), "", "", self.currentTask.level + 1, self.currentTask.start, 1);
+ row = self.currentTask.getRow() + 1;
+ } else {
+ ch = factory.build("tmp_" + new Date().getTime(), "", "", 0, new Date().getTime(), 1);
+ }
+ var task = self.addTask(ch, row);
+ if (task) {
+ task.rowElement.click();
+ task.rowElement.find("[name=name]").focus();
+ }
+ self.endTransaction();
+
+
+ }).bind("indentCurrentTask.gantt", function() {
+ if (self.currentTask) {
+ self.beginTransaction();
+ self.currentTask.indent();
+ self.endTransaction();
+ }
+
+ }).bind("outdentCurrentTask.gantt", function() {
+ if (self.currentTask) {
+ self.beginTransaction();
+ self.currentTask.outdent();
+ self.endTransaction();
+ }
+
+ }).bind("moveUpCurrentTask.gantt", function() {
+ if (self.currentTask) {
+ self.beginTransaction();
+ self.currentTask.moveUp();
+ self.endTransaction();
+ }
+ }).bind("moveDownCurrentTask.gantt", function() {
+ if (self.currentTask) {
+ self.beginTransaction();
+ self.currentTask.moveDown();
+ self.endTransaction();
+ }
+
+ }).bind("zoomPlus.gantt", function() {
+ self.gantt.zoomGantt(true);
+ }).bind("zoomMinus.gantt", function() {
+ self.gantt.zoomGantt(false);
+
+ }).bind("undo.gantt", function() {
+ self.undo();
+ }).bind("redo.gantt", function() {
+ self.redo();
+ });
+};
+
+GanttMaster.messages = {
+ "CHANGE_OUT_OF_SCOPE": "NO_RIGHTS_FOR_UPDATE_PARENTS_OUT_OF_EDITOR_SCOPE",
+ "START_IS_MILESTONE": "START_IS_MILESTONE",
+ "END_IS_MILESTONE": "END_IS_MILESTONE",
+ "TASK_HAS_CONSTRAINTS": "TASK_HAS_CONSTRAINTS",
+ "GANTT_ERROR_DEPENDS_ON_OPEN_TASK": "GANTT_ERROR_DEPENDS_ON_OPEN_TASK",
+ "GANTT_ERROR_DESCENDANT_OF_CLOSED_TASK":"GANTT_ERROR_DESCENDANT_OF_CLOSED_TASK",
+ "TASK_HAS_EXTERNAL_DEPS": "TASK_HAS_EXTERNAL_DEPS",
+ "GANTT_ERROR_LOADING_DATA_TASK_REMOVED":"GANTT_ERROR_LOADING_DATA_TASK_REMOVED",
+ "CIRCULAR_REFERENCE": "CIRCULAR_REFERENCE",
+ "ERROR_SETTING_DATES": "ERROR_SETTING_DATES",
+ "CANNOT_DEPENDS_ON_ANCESTORS": "CANNOT_DEPENDS_ON_ANCESTORS",
+ "CANNOT_DEPENDS_ON_DESCENDANTS": "CANNOT_DEPENDS_ON_DESCENDANTS",
+ "INVALID_DATE_FORMAT": "INVALID_DATE_FORMAT",
+ "GANTT_QUARTER_SHORT": "GANTT_QUARTER_SHORT",
+ "GANTT_SEMESTER_SHORT":"GANTT_SEMESTER_SHORT"
+};
+
+
+GanttMaster.prototype.createTask = function (id, name, code, level, start, duration) {
+ var factory = new TaskFactory();
+
+ return factory.build(id, name, code, level, start, duration);
+};
+
+
+GanttMaster.prototype.createResource = function (id, name) {
+ var res = new Resource(id, name);
+ return res;
+};
+
+
+//update depends strings
+GanttMaster.prototype.updateDependsStrings = function() {
+ //remove all deps
+ for (var i=0;i<this.tasks.length;i++) {
+ this.tasks[i].depends = "";
+ }
+
+ for (var i=0;i<this.links.length;i++) {
+ var link = this.links[i];
+ var dep = link.to.depends;
+ link.to.depends = link.to.depends + (link.to.depends == "" ? "" : ",") + (link.from.getRow() + 1) + (link.lag ? ":" + link.lag : "");
+ }
+
+};
+
+//------------------------------------ ADD TASK --------------------------------------------
+GanttMaster.prototype.addTask = function(task, row) {
+ //console.debug("master.addTask",task,row,this);
+ task.master = this; // in order to access controller from task
+
+ //replace if already exists
+ var pos = -1;
+ for (var i=0;i<this.tasks.length;i++) {
+ if (task.id == this.tasks[i].id) {
+ pos = i;
+ break;
+ }
+ }
+
+ if (pos >= 0) {
+ this.tasks.splice(pos, 1);
+ row = parseInt(pos);
+ }
+
+ //add task in collection
+ if (typeof(row) != "number") {
+ this.tasks.push(task);
+ } else {
+ this.tasks.splice(row, 0, task);
+
+ //recompute depends string
+ this.updateDependsStrings();
+ }
+
+ //add Link collection in memory
+ var linkLoops = !this.updateLinks(task);
+
+ //set the status according to parent
+ if (task.getParent())
+ task.status=task.getParent().status;
+ else
+ task.status="STATUS_ACTIVE";
+
+
+ var ret = task;
+ if (linkLoops || !task.setPeriod(task.start, task.end)) {
+ //remove task from in-memory collection
+ //console.debug("removing task from memory",task);
+ this.tasks.splice(task.getRow(), 1);
+ ret = undefined;
+ } else {
+ //append task to editor
+ this.editor.addTask(task, row);
+ //append task to gantt
+ this.gantt.addTask(task);
+ }
+ return ret;
+};
+
+
+/**
+ * a project contais tasks, resources, roles, and info about permisions
+ * @param project
+ */
+GanttMaster.prototype.loadProject = function(project) {
+ this.beginTransaction();
+ this.resources = project.resources;
+ this.roles = project.roles;
+ this.canWrite = project.canWrite;
+ this.canWriteOnParent = project.canWriteOnParent;
+
+ if (project.minEditableDate)
+ this.minEditableDate = computeStart(project.minEditableDate);
+ else
+ this.minEditableDate =-Infinity;
+
+ if (project.maxEditableDate)
+ this.maxEditableDate =computeEnd(project.maxEditableDate);
+ else
+ this.maxEditableDate =Infinity;
+
+ this.loadTasks(project.tasks, project.selectedRow);
+ this.deletedTaskIds=[];
+ this.endTransaction();
+ var self=this;
+ this.gantt.element.oneTime(200,function(){self.gantt.centerOnToday()});
+};
+
+
+GanttMaster.prototype.loadTasks = function(tasks, selectedRow) {
+ var factory = new TaskFactory();
+ //reset
+ this.reset();
+
+ for (var i=0;i<tasks.length;i++){
+ var task = tasks[i];
+ if (!(task instanceof Task)) {
+ var t = factory.build(task.id, task.name, task.code, task.level, task.start, task.duration);
+ for (var key in task) {
+ if (key!="end" && key!="start")
+ t[key] = task[key]; //copy all properties
+ }
+ task = t;
+ }
+ task.master = this; // in order to access controller from task
+
+ /*//replace if already exists
+ var pos = -1;
+ for (var i=0;i<this.tasks.length;i++) {
+ if (task.id == this.tasks[i].id) {
+ pos = i;
+ break;
+ }
+ }*/
+
+ this.tasks.push(task); //append task at the end
+ }
+
+ //var prof=new Profiler("gm_loadTasks_addTaskLoop");
+ for (var i=0;i<this.tasks.length;i++) {
+ var task = this.tasks[i];
+
+ //add Link collection in memory
+ var linkLoops = !this.updateLinks(task);
+
+ if (linkLoops || !task.setPeriod(task.start, task.end)) {
+ alert(GanttMaster.messages.GANNT_ERROR_LOADING_DATA_TASK_REMOVED+"\n" + task.name+"\n"+
+ (linkLoops?GanttMaster.messages.CIRCULAR_REFERENCE:GanttMaster.messages.ERROR_SETTING_DATES));
+
+ //remove task from in-memory collection
+ this.tasks.splice(task.getRow(), 1);
+ } else {
+ //append task to editor
+ this.editor.addTask(task);
+ //append task to gantt
+ this.gantt.addTask(task);
+ }
+ }
+
+ this.editor.fillEmptyLines();
+ //prof.stop();
+
+ // re-select old row if tasks is not empty
+ if (this.tasks && this.tasks.length>0){
+ selectedRow = selectedRow ? selectedRow : 0;
+ this.tasks[selectedRow].rowElement.click();
+ }
+
+};
+
+
+GanttMaster.prototype.getTask = function(taskId) {
+ var ret;
+ for (var i=0;i<this.tasks.length;i++) {
+ var tsk = this.tasks[i];
+ if (tsk.id == taskId) {
+ ret = tsk;
+ break;
+ }
+ }
+ return ret;
+};
+
+
+GanttMaster.prototype.getResource = function(resId) {
+ var ret;
+ for (var i=0;i<this.resources.length;i++) {
+ var res = this.resources[i];
+ if (res.id == resId) {
+ ret = res;
+ break;
+ }
+ }
+ return ret;
+};
+
+
+GanttMaster.prototype.changeTaskDates = function(task, start, end) {
+ return task.setPeriod(start, end);
+};
+
+
+GanttMaster.prototype.moveTask = function(task, newStart) {
+ return task.moveTo(newStart, true);
+};
+
+
+GanttMaster.prototype.taskIsChanged = function() {
+ //console.debug("taskIsChanged");
+ var master=this;
+
+ //refresh is executed only once every 50ms
+ this.element.stopTime("gnnttaskIsChanged");
+ //var profilerext = new Profiler("gm_taskIsChangedRequest");
+ this.element.oneTime(50, "gnnttaskIsChanged", function() {
+ //console.debug("task Is Changed real call to redraw");
+ //var profiler = new Profiler("gm_taskIsChangedReal");
+ master.editor.redraw();
+ master.gantt.refreshGantt();
+ //profiler.stop();
+ });
+ //profilerext.stop();
+};
+
+
+GanttMaster.prototype.redraw = function() {
+ this.editor.redraw();
+ this.gantt.refreshGantt();
+};
+
+GanttMaster.prototype.reset = function() {
+ this.tasks = [];
+ this.links = [];
+ this.deletedTaskIds=[];
+ this.__undoStack = [];
+ this.__redoStack = [];
+ delete this.currentTask;
+
+ this.editor.reset();
+ this.gantt.reset();
+};
+
+
+GanttMaster.prototype.showTaskEditor = function(taskId) {
+ var task = this.getTask(taskId);
+ task.rowElement.find(".edit").click();
+};
+
+GanttMaster.prototype.saveProject = function() {
+ return this.saveGantt(false);
+};
+
+GanttMaster.prototype.saveGantt = function(forTransaction) {
+ //var prof = new Profiler("gm_saveGantt");
+ var saved = [];
+ for (var i=0;i<this.tasks.length;i++) {
+ var task = this.tasks[i];
+ var cloned = task.clone();
+ delete cloned.master;
+ delete cloned.rowElement;
+ delete cloned.ganttElement;
+
+ saved.push(cloned);
+ }
+
+ var ret = {tasks:saved};
+ if (this.currentTask) {
+ ret.selectedRow = this.currentTask.getRow();
+ }
+
+ ret.deletedTaskIds=this.deletedTaskIds; //this must be consistent with transactions and undo
+
+ if (!forTransaction) {
+ ret.resources = this.resources;
+ ret.roles = this.roles;
+ ret.canWrite = this.canWrite;
+ ret.canWriteOnParent = this.canWriteOnParent;
+ }
+
+ //prof.stop();
+ return ret;
+};
+
+
+GanttMaster.prototype.updateLinks = function(task) {
+ //console.debug("updateLinks");
+ //var prof= new Profiler("gm_updateLinks");
+
+ // defines isLoop function
+ function isLoop(task, target, visited) {
+ if (target == task) {
+ return true;
+ }
+
+ var sups = task.getSuperiors();
+ var loop = false;
+ for (var i=0;i<sups.length;i++) {
+ var supLink = sups[i];
+ if (supLink.from == target) {
+ loop = true;
+ break;
+ } else {
+ if (visited.indexOf(supLink.from) <= 0) {
+ visited.push(supLink.from);
+ if (isLoop(supLink.from, target, visited)) {
+ loop = true;
+ break;
+ }
+ }
+ }
+ }
+ return loop;
+ }
+
+ //remove my depends
+ this.links = this.links.filter(function(link) {
+ return link.to != task;
+ });
+
+ var todoOk = true;
+ if (task.depends) {
+
+ //cannot depend from an ancestor
+ var parents = task.getParents();
+ //cannot depend from descendants
+ var descendants=task.getDescendant();
+
+ var deps = task.depends.split(",");
+ var newDepsString = "";
+
+ var visited = [];
+ for (var j=0;j<deps.length;j++) {
+ var dep = deps[j]; // in the form of row(lag) e.g. 2:3,3:4,5
+ var par = dep.split(":");
+ var lag = 0;
+
+ if (par.length > 1) {
+ lag = parseInt(par[1]);
+ }
+
+ var sup = this.tasks[parseInt(par[0] - 1)];
+
+ if (sup) {
+ if (parents && parents.indexOf(sup) >= 0) {
+ this.setErrorOnTransaction(task.name + "\n"+GanttMaster.messages.CANNOT_DEPENDS_ON_ANCESTORS+"\n" + sup.name);
+ todoOk = false;
+
+ } else if (descendants && descendants.indexOf(sup) >= 0) {
+ this.setErrorOnTransaction(task.name + "\n"+GanttMaster.messages.CANNOT_DEPENDS_ON_DESCENDANTS+"\n" + sup.name);
+ todoOk = false;
+
+ } else if (isLoop(sup, task, visited)) {
+ todoOk = false;
+ this.setErrorOnTransaction(GanttMaster.messages.CIRCULAR_REFERENCE+"\n" + task.name + " -> " + sup.name);
+ } else {
+ this.links.push(new Link(sup, task, lag));
+ newDepsString = newDepsString + (newDepsString.length > 0 ? "," : "") + dep;
+ }
+ }
+ }
+
+ if (todoOk) {
+ task.depends = newDepsString;
+ }
+
+ }
+
+ //prof.stop();
+
+ return todoOk;
+};
+
+
+//<%----------------------------- TRANSACTION MANAGEMENT ---------------------------------%>
+GanttMaster.prototype.beginTransaction = function() {
+ if (!this.__currentTransaction) {
+ this.__currentTransaction = {
+ snapshot:JSON.stringify(this.saveGantt(true)),
+ errors:[]
+ };
+ } else {
+ console.error("Cannot open twice a transaction");
+ }
+ return this.__currentTransaction;
+};
+
+
+GanttMaster.prototype.endTransaction = function() {
+ if (!this.__currentTransaction) {
+ console.error("Transaction never started.");
+ return true;
+ }
+
+ var ret = true;
+
+ //no error -> commit
+ if (this.__currentTransaction.errors.length <= 0) {
+ //console.debug("committing transaction");
+
+ //put snapshot in undo
+ this.__undoStack.push(this.__currentTransaction.snapshot);
+ //clear redo stack
+ this.__redoStack = [];
+
+ //shrink gantt bundaries
+ this.gantt.originalStartMillis = Infinity;
+ this.gantt.originalEndMillis = -Infinity;
+ for (var i=0;i<this.tasks.length;i++) {
+ var task = this.tasks[i];
+ if (this.gantt.originalStartMillis > task.start)
+ this.gantt.originalStartMillis = task.start;
+ if (this.gantt.originalEndMillis < task.end)
+ this.gantt.originalEndMillis = task.end;
+
+ }
+ this.taskIsChanged(); //enqueue for gantt refresh
+
+
+ //error -> rollback
+ } else {
+ ret = false;
+ //console.debug("rolling-back transaction");
+ //try to restore changed tasks
+ var oldTasks = JSON.parse(this.__currentTransaction.snapshot);
+ this.deletedTaskIds=oldTasks.deletedTaskIds;
+ this.loadTasks(oldTasks.tasks, oldTasks.selectedRow);
+ this.redraw();
+
+ //compose error message
+ var msg = "";
+ for (var i=0;i<this.__currentTransaction.errors.length;i++) {
+ var err = this.__currentTransaction.errors[i];
+ msg = msg + err.msg + "\n\n";
+ }
+ alert(msg);
+ }
+ //reset transaction
+ this.__currentTransaction = undefined;
+
+ return ret;
+};
+
+//this function notify an error to a transaction -> transaction will rollback
+GanttMaster.prototype.setErrorOnTransaction = function(errorMessage, task) {
+ if (this.__currentTransaction) {
+ this.__currentTransaction.errors.push({msg:errorMessage,task:task});
+ } else {
+ console.error(errorMessage);
+ }
+};
+
+// inhibit undo-redo
+GanttMaster.prototype.checkpoint= function() {
+ this.__undoStack = [];
+ this.__redoStack = [];
+};
+
+//----------------------------- UNDO/REDO MANAGEMENT ---------------------------------%>
+
+GanttMaster.prototype.undo = function() {
+ //console.debug("undo before:",undoStack,redoStack);
+ if (this.__undoStack.length > 0) {
+ var his = this.__undoStack.pop();
+ this.__redoStack.push(JSON.stringify(this.saveGantt()));
+
+ var oldTasks = JSON.parse(his);
+ this.deletedTaskIds=oldTasks.deletedTaskIds;
+ this.loadTasks(oldTasks.tasks, oldTasks.selectedRow);
+ //console.debug(oldTasks,oldTasks.deletedTaskIds)
+ this.redraw();
+ //console.debug("undo after:",undoStack,redoStack);
+ }
+};
+
+GanttMaster.prototype.redo = function() {
+ //console.debug("redo before:",undoStack,redoStack);
+ if (this.__redoStack.length > 0) {
+ var his = this.__redoStack.pop();
+ this.__undoStack.push(JSON.stringify(this.saveGantt()));
+
+ var oldTasks = JSON.parse(his);
+ this.deletedTaskIds=oldTasks.deletedTaskIds;
+ this.loadTasks(oldTasks.tasks, oldTasks.selectedRow);
+ this.redraw();
+ //console.debug("redo after:",undoStack,redoStack);
+ }
+};
+
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttTask.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttTask.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttTask.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,947 @@
+/*
+ Copyright (c) 2012-2013 Open Lab
+ Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/**
+ * A method to instantiate valid task models from
+ * raw data.
+ */
+function TaskFactory() {
+
+ /**
+ * Build a new Task
+ */
+ this.build = function(id, name, code, level, start, duration) {
+ // Set at beginning of day
+ var adjusted_start = computeStart(start);
+ var calculated_end = computeEndByDuration(adjusted_start, duration);
+
+ return new Task(id, name, code, level, adjusted_start, calculated_end, duration);
+ };
+
+}
+
+function Task(id, name, code, level, start, end, duration) {
+ this.id = id;
+ this.name = name;
+ this.code = code;
+ this.level = level;
+ this.status = "STATUS_UNDEFINED";
+
+ this.start = start
+ this.duration = duration;
+ this.end = end;
+
+ this.startIsMilestone = false;
+ this.endIsMilestone = false;
+
+ this.collapsed = false;
+
+ this.rowElement; //row editor html element
+ this.ganttElement; //gantt html element
+ this.master;
+
+ this.assigs = [];
+}
+
+Task.prototype.clone = function () {
+ var ret = {};
+ for (var key in this) {
+ if (typeof(this[key]) != "function") {
+ ret[key] = this[key];
+ }
+ }
+ return ret;
+};
+
+Task.prototype.getAssigsString = function () {
+ var ret = "";
+ for (var i=0;i<this.assigs.length;i++) {
+ var ass = this.assigs[i];
+ var res = this.master.getResource(ass.resourceId);
+ if (res) {
+ ret = ret + (ret == "" ? "" : ", ") + res.name;
+ }
+ }
+ return ret;
+};
+
+Task.prototype.createAssignment = function (id, resourceId, roleId, effort) {
+ var assig = new Assignment(id, resourceId, roleId, effort);
+ this.assigs.push(assig);
+ return assig;
+};
+
+
+//<%---------- SET PERIOD ---------------------- --%>
+Task.prototype.setPeriod = function (start, end) {
+ //console.debug("setPeriod ",this.name,new Date(start),new Date(end));
+ //var profilerSetPer = new Profiler("gt_setPeriodJS");
+
+ if (start instanceof Date) {
+ start = start.getTime();
+ }
+
+ if (end instanceof Date) {
+ end = end.getTime();
+ }
+
+ var originalPeriod = {
+ start: this.start,
+ end: this.end,
+ duration: this.duration
+ };
+
+ //console.debug("setStart",date,date instanceof Date);
+ var wantedStartMillis = start;
+
+ //cannot start after end
+ if (start > end) {
+ start = end;
+ }
+
+ //set a legal start
+ start = computeStart(start);
+
+ //if depends -> start is set to max end + lag of superior
+ var sups = this.getSuperiors();
+ if (sups && sups.length > 0) {
+
+ var supEnd = 0;
+ for (var i=0;i<sups.length;i++) {
+ var link = sups[i];
+ supEnd = Math.max(supEnd, incrementDateByWorkingDays(link.from.end, link.lag));
+ }
+ //if changed by depends move it
+ if (computeStart(supEnd) != start) {
+ return this.moveTo(supEnd + 1, false);
+ }
+ }
+
+ var somethingChanged = false;
+
+ //move date to closest day
+ var date = new Date(start);
+
+ if (this.start != start || this.start != wantedStartMillis) {
+ this.start = start;
+ somethingChanged = true;
+ }
+
+ //set end
+ var wantedEndMillis = end;
+
+ end = computeEnd(end);
+
+ if (this.end != end || this.end != wantedEndMillis) {
+ this.end = end;
+ somethingChanged = true;
+ }
+
+ this.duration = recomputeDuration(this.start, this.end);
+
+ //profilerSetPer.stop();
+
+ //nothing changed exit
+ if (!somethingChanged)
+ return true;
+
+ //external dependencies: exit with error
+ if (this.hasExternalDep) {
+ this.master.setErrorOnTransaction(GanttMaster.messages["TASK_HAS_EXTERNAL_DEPS"] + "\n" + this.name, this);
+ return false;
+ }
+
+ var todoOk = true;
+
+ //I'm restricting
+ var deltaPeriod = originalPeriod.duration - this.duration;
+ var restricting = deltaPeriod > 0;
+ var restrictingStart = restricting && (originalPeriod.start < this.start);
+ var restrictingEnd = restricting && (originalPeriod.end > this.end);
+
+ //console.debug( " originalPeriod.duration "+ originalPeriod.duration +" deltaPeriod "+deltaPeriod+" "+"restricting "+restricting);
+
+ if (restricting) {
+ //loops children to get boundaries
+ var children = this.getChildren();
+ var bs = Infinity;
+ var be = 0;
+ for (var i=0;i<children.length;i++) {
+
+ ch = children[i];
+ //console.debug("restricting: test child "+ch.name+" "+ch.end)
+ if (restrictingEnd) {
+ be = Math.max(be, ch.end);
+ } else {
+ bs = Math.min(bs, ch.start);
+ }
+ }
+
+ if (restrictingEnd) {
+ //console.debug("restricting end ",be, this.end);
+ this.end = Math.max(be, this.end);
+ } else {
+ //console.debug("restricting start");
+ this.start = Math.min(bs, this.start);
+ }
+
+ this.duration = recomputeDuration(this.start, this.end);
+ } else {
+
+ //check global boundaries
+ if (this.start < this.master.minEditableDate || this.end > this.master.maxEditableDate) {
+ this.master.setErrorOnTransaction(GanttMaster.messages["CHANGE_OUT_OF_SCOPE"], this);
+ todoOk = false;
+ }
+
+ //console.debug("set period: somethingChanged",this);
+ if (todoOk && !updateTree(this)) {
+ todoOk = false;
+ }
+ }
+
+ if (todoOk) {
+ //and now propagate to inferiors
+ var infs = this.getInferiors();
+ if (infs && infs.length > 0) {
+ for (var i=0;i<infs.length;i++) {
+ var link = infs[i];
+ todoOk = link.to.moveTo(end, false); //this is not the right date but moveTo checks start
+ if (!todoOk)
+ break;
+ }
+ }
+ }
+
+ return todoOk;
+};
+
+
+//<%---------- MOVE TO ---------------------- --%>
+Task.prototype.moveTo = function (start, ignoreMilestones) {
+ //console.debug("moveTo ",this,start,ignoreMilestones);
+ //var profiler = new Profiler("gt_task_moveTo");
+
+ if (start instanceof Date) {
+ start = start.getTime();
+ }
+
+ var originalPeriod = {
+ start:this.start,
+ end:this.end
+ };
+
+ var wantedStartMillis = start;
+
+ //set a legal start
+ start = computeStart(start);
+
+ //if start is milestone cannot be move
+ if (!ignoreMilestones && this.startIsMilestone && start != this.start) {
+ //notify error
+ this.master.setErrorOnTransaction(GanttMaster.messages["START_IS_MILESTONE"], this);
+ return false;
+ } else if (this.hasExternalDep) {
+ //notify error
+ this.master.setErrorOnTransaction(GanttMaster.messages["TASK_HAS_EXTERNAL_DEPS"], this);
+ return false;
+ }
+
+ //if depends start is set to max end + lag of superior
+ var sups = this.getSuperiors();
+ if (sups && sups.length > 0) {
+ var supEnd = 0;
+ for (var i=0;i<sups.length;i++) {
+ var link = sups[i];
+ supEnd = Math.max(supEnd, incrementDateByWorkingDays(link.from.end, link.lag));
+ }
+ start = supEnd + 1;
+ }
+ //set a legal start
+ start = computeStart(start);
+
+ var end = computeEndByDuration(start, this.duration);
+
+ if (this.start != start || this.start != wantedStartMillis) {
+ //in case of end is milestone it never changes, but recompute duration
+ if (!ignoreMilestones && this.endIsMilestone) {
+ end = this.end;
+ this.duration = recomputeDuration(start, end);
+ }
+ this.start = start;
+ this.end = end;
+ //profiler.stop();
+
+ //check global boundaries
+ if (this.start < this.master.minEditableDate || this.end > this.master.maxEditableDate) {
+ this.master.setErrorOnTransaction(GanttMaster.messages["CHANGE_OUT_OF_SCOPE"], this);
+ return false;
+ }
+
+
+ var panDelta = originalPeriod.start - this.start;
+ //console.debug("panDelta",panDelta);
+ //loops children to shift them
+ var children = this.getChildren();
+ for (var i=0;i<children.length;i++) {
+ ch = children[i];
+ if (!ch.moveTo(ch.start - panDelta, false)) {
+ return false;
+ }
+ }
+
+
+ //console.debug("set period: somethingChanged",this);
+ if (!updateTree(this)) {
+ return false;
+ }
+
+
+ //and now propagate to inferiors
+ var infs = this.getInferiors();
+ if (infs && infs.length > 0) {
+ for (var i=0;i<infs.length;i++) {
+ var link = infs[i];
+
+ //this is not the right date but moveTo checks start
+ if (!link.to.moveTo(end, false)) {
+ return false;
+ }
+ }
+ }
+
+ }
+
+ return true;
+};
+
+
+function updateTree(task) {
+ //console.debug("updateTree ",task);
+ var error;
+
+ //try to enlarge parent
+ var p = task.getParent();
+
+ //no parent:exit
+ if (!p)
+ return true;
+
+
+ var newStart = p.start;
+ var newEnd = p.end;
+
+ if (p.start > task.start) {
+ if (p.startIsMilestone) {
+ task.master.setErrorOnTransaction(GanttMaster.messages["START_IS_MILESTONE"] + "\n" + p.name, task);
+ return false;
+ } else if (p.depends) {
+ task.master.setErrorOnTransaction(GanttMaster.messages["TASK_HAS_CONSTRAINTS"] + "\n" + p.name, task);
+ return false;
+ }
+
+ newStart = task.start;
+ }
+
+ if (p.end < task.end) {
+ if (p.endIsMilestone) {
+ task.master.setErrorOnTransaction(GanttMaster.messages["END_IS_MILESTONE"] + "\n" + p.name, task);
+ return false;
+ }
+
+ newEnd = task.end;
+ }
+
+ //propagate updates if needed
+ if (newStart != p.start || newEnd != p.end) {
+ //has external deps ?
+ if (p.hasExternalDep) {
+ task.master.setErrorOnTransaction(GanttMaster.messages["TASK_HAS_EXTERNAL_DEPS"] + "\n" + p.name, task);
+ return false;
+ }
+
+ return p.setPeriod(newStart, newEnd);
+ }
+
+
+ return true;
+}
+
+//<%---------- CHANGE STATUS ---------------------- --%>
+Task.prototype.changeStatus = function(newStatus) {
+ //console.debug("changeStatus: "+this.name+" from "+this.status+" -> "+newStatus);
+ //compute descendant for identify a cone where status changes propagate
+ var cone = this.getDescendant();
+
+ function propagateStatus(task, newStatus, manuallyChanged, propagateFromParent, propagateFromChildren) {
+ var oldStatus = task.status;
+
+ //no changes exit
+ if(newStatus == oldStatus){
+ return true;
+ }
+ //console.debug("propagateStatus: "+task.name + " from " + task.status + " to " + newStatus + " " + (manuallyChanged?" a manella":"")+(propagateFromParent?" da parent":"")+(propagateFromChildren?" da children":""));
+
+ var todoOk = true;
+ task.status = newStatus;
+
+ //xxxx -> STATUS_DONE may activate dependent tasks, both suspended and undefined. Will set to done all descendants.
+ //STATUS_FAILED -> STATUS_DONE do nothing if not forced by hand
+ if (newStatus == "STATUS_DONE") {
+
+ if ((manuallyChanged || oldStatus != "STATUS_FAILED")) { //cannot change for cascade when failed
+
+ //can be closed only if superiors are already done
+ var sups = task.getSuperiors();
+ for (var i=0;i<sups.length;i++) {
+ if (cone.indexOf(sups[i].from) < 0) {
+ if (sups[i].from.status != "STATUS_DONE") {
+ if (manuallyChanged || propagateFromParent)
+ task.master.setErrorOnTransaction(GanttMaster.messages["GANTT_ERROR_DEPENDS_ON_OPEN_TASK"] + "\n" + sups[i].from.name + " -> " + task.name);
+ todoOk = false;
+ break;
+ }
+ }
+ }
+
+ if (todoOk) {
+ //todo set progress to 100% if set on config
+
+ var chds = task.getChildren();
+ //set children as done
+ for (var i=0;i<chds.length;i++)
+ propagateStatus(chds[i], "STATUS_DONE", false,true,false);
+
+ //set inferiors as active if outside the cone
+ propagateToInferiors(cone, task.getInferiors(), "STATUS_ACTIVE");
+ }
+ } else {
+ todoOk = false;
+ }
+
+
+ // STATUS_UNDEFINED -> STATUS_ACTIVE all children become active, if they have no dependencies.
+ // STATUS_SUSPENDED -> STATUS_ACTIVE sets to active all children and their descendants that have no inhibiting dependencies.
+ // STATUS_DONE -> STATUS_ACTIVE all those that have dependencies must be set to suspended.
+ // STATUS_FAILED -> STATUS_ACTIVE nothing happens: child statuses must be reset by hand.
+ } else if (newStatus == "STATUS_ACTIVE") {
+
+ if ((manuallyChanged || oldStatus != "STATUS_FAILED")) { //cannot change for cascade when failed
+
+ //activate parent if closed
+ var par=task.getParent();
+ if (par && par.status != "STATUS_ACTIVE") {
+ todoOk=propagateStatus(par,"STATUS_ACTIVE",false,false,true);
+ }
+
+ if(todoOk){
+ //can be active only if superiors are already done
+ var sups = task.getSuperiors();
+ for (var i=0;i<sups.length;i++) {
+ if (sups[i].from.status != "STATUS_DONE") {
+ if (manuallyChanged || propagateFromChildren)
+ task.master.setErrorOnTransaction(GanttMaster.messages["GANTT_ERROR_DEPENDS_ON_OPEN_TASK"] + "\n" + sups[i].from.name + " -> " + task.name);
+ todoOk = false;
+ break;
+ }
+ }
+ }
+
+ if (todoOk) {
+ var chds = task.getChildren();
+ if (oldStatus == "STATUS_UNDEFINED" || oldStatus == "STATUS_SUSPENDED") {
+ //set children as active
+ for (var i=0;i<chds.length;i++)
+ if (chds[i].status != "STATUS_DONE" )
+ propagateStatus(chds[i], "STATUS_ACTIVE", false,true,false);
+ }
+
+ //set inferiors as suspended
+ var infs = task.getInferiors();
+ for (var i=0;i<infs.length;i++)
+ propagateStatus(infs[i].to, "STATUS_SUSPENDED", false,false,false);
+ }
+ } else {
+ todoOk = false;
+ }
+
+ // xxxx -> STATUS_SUSPENDED all active children and their active descendants become suspended. when not failed or forced
+ // xxxx -> STATUS_UNDEFINED all active children and their active descendants become suspended. when not failed or forced
+ } else if (newStatus == "STATUS_SUSPENDED" || newStatus == "STATUS_UNDEFINED") {
+ if (manuallyChanged || oldStatus != "STATUS_FAILED") { //cannot change for cascade when failed
+
+ //suspend parent if not active
+ var par=task.getParent();
+ if (par && par.status != "STATUS_ACTIVE") {
+ todoOk=propagateStatus(par,newStatus,false,false,true);
+ }
+
+
+ var chds = task.getChildren();
+ //set children as active
+ for (var i=0;i<chds.length;i++){
+ if (chds[i].status != "STATUS_DONE")
+ propagateStatus(chds[i], newStatus, false,true,false);
+ }
+
+ //set inferiors as STATUS_SUSPENDED or STATUS_UNDEFINED
+ propagateToInferiors(cone, task.getInferiors(), newStatus);
+ } else {
+ todoOk = false;
+ }
+
+ // xxxx -> STATUS_FAILED children and dependent failed
+ } else if (newStatus == "STATUS_FAILED") {
+ var chds = task.getChildren();
+ //set children as failed
+ for (var i=0;i<chds.length;i++)
+ propagateStatus(chds[i], "STATUS_FAILED", false,true,false);
+
+ //set inferiors as active
+ //set children as done
+ propagateToInferiors(cone, task.getInferiors(), "STATUS_FAILED");
+ }
+ if (!todoOk){
+ task.status = oldStatus;
+ //console.debug("status rolled back: "+task.name + " to " + oldStatus);
+ }
+
+ return todoOk;
+ }
+
+ /**
+ * A helper method to traverse an array of 'inferior' tasks
+ * and signal a status change.
+ */
+ function propagateToInferiors(cone, infs, status) {
+ for (var i=0;i<infs.length;i++) {
+ if (cone.indexOf(infs[i].to) < 0) {
+ propagateStatus(infs[i].to, status, false, false, false);
+ }
+ }
+ }
+
+ var todoOk = true;
+ var oldStatus = this.status;
+
+ todoOk = propagateStatus(this, newStatus, true,false,false);
+
+ if (!todoOk)
+ this.status = oldStatus;
+
+ return todoOk;
+};
+
+Task.prototype.synchronizeStatus=function(){
+ var oldS=this.status;
+ this.status="";
+ return this.changeStatus(oldS);
+};
+
+Task.prototype.isLocallyBlockedByDependencies=function(){
+ var sups = this.getSuperiors();
+ var blocked=false;
+ for (var i=0;i<sups.length;i++) {
+ if (sups[i].from.status != "STATUS_DONE") {
+ blocked=true;
+ break;
+ }
+ }
+ return blocked;
+};
+
+//<%---------- TASK STRUCTURE ---------------------- --%>
+Task.prototype.getRow = function() {
+ ret = -1;
+ if (this.master)
+ ret = this.master.tasks.indexOf(this);
+ return ret;
+};
+
+
+Task.prototype.getParents = function() {
+ var ret;
+ if (this.master) {
+ var topLevel = this.level;
+ var pos = this.getRow();
+ ret = [];
+ for (var i = pos; i >= 0; i--) {
+ var par = this.master.tasks[i];
+ if (topLevel > par.level) {
+ topLevel = par.level;
+ ret.push(par);
+ }
+ }
+ }
+ return ret;
+};
+
+
+Task.prototype.getParent = function() {
+ var ret;
+ if (this.master) {
+ for (var i = this.getRow(); i >= 0; i--) {
+ var par = this.master.tasks[i];
+ if (this.level > par.level) {
+ ret = par;
+ break;
+ }
+ }
+ }
+ return ret;
+};
+
+
+Task.prototype.isParent = function() {
+ var ret = false;
+ if (this.master) {
+ var pos = this.getRow();
+ if (pos < this.master.tasks.length - 1)
+ ret = this.master.tasks[pos + 1].level > this.level;
+ }
+ return ret;
+};
+
+
+Task.prototype.getChildren = function() {
+ var ret = [];
+ if (this.master) {
+ var pos = this.getRow();
+ for (var i = pos + 1; i < this.master.tasks.length; i++) {
+ var ch = this.master.tasks[i];
+ if (ch.level == this.level + 1)
+ ret.push(ch);
+ else if (ch.level <= this.level) // exit loop if parent or brother
+ break;
+ }
+ }
+ return ret;
+};
+
+
+Task.prototype.getDescendant = function() {
+ var ret = [];
+ if (this.master) {
+ var pos = this.getRow();
+ for (var i = pos + 1; i < this.master.tasks.length; i++) {
+ var ch = this.master.tasks[i];
+ if (ch.level > this.level)
+ ret.push(ch);
+ else
+ break;
+ }
+ }
+ return ret;
+};
+
+
+Task.prototype.getSuperiors = function() {
+ var ret = [];
+ var task = this;
+ if (this.master) {
+ ret = this.master.links.filter(function(link) {
+ return link.to == task;
+ });
+ }
+ return ret;
+};
+
+
+Task.prototype.getInferiors = function() {
+ var ret = [];
+ var task = this;
+ if (this.master) {
+ ret = this.master.links.filter(function(link) {
+ return link.from == task;
+ });
+ }
+ return ret;
+};
+
+
+Task.prototype.deleteTask = function() {
+ //delete both dom elements
+ this.rowElement.remove();
+ this.ganttElement.remove();
+
+ //remove children
+ var chd = this.getChildren();
+ for (var i=0;i<chd.length;i++) {
+ //add removed child in list
+ if(!chd[i].isNew())
+ this.master.deletedTaskIds.push(chd[i].id);
+ chd[i].deleteTask();
+ }
+
+ if(!this.isNew())
+ this.master.deletedTaskIds.push(this.id);
+
+
+ //remove from in-memory collection
+ this.master.tasks.splice(this.getRow(), 1);
+
+ //remove from links
+ var task = this;
+ this.master.links = this.master.links.filter(function(link) {
+ return link.from != task && link.to != task;
+ });
+};
+
+
+Task.prototype.isNew=function(){
+ return (this.id+"").indexOf("tmp_")==0;
+};
+
+//<%------------------------------------------ INDENT/OUTDENT --------------------------------%>
+Task.prototype.indent = function() {
+ //console.debug("indent", this);
+ //a row above must exist
+ var row = this.getRow();
+
+ //no row no party
+ if (row <=0)
+ return false;
+
+ var ret = false;
+ var taskAbove = this.master.tasks[row - 1];
+ var newLev = this.level + 1;
+ if (newLev <= taskAbove.level + 1) {
+ ret = true;
+ //trick to get parents after indent
+ this.level++;
+ var futureParents = this.getParents();
+ this.level--;
+ var oldLevel = this.level;
+ for (var i = row; i < this.master.tasks.length; i++) {
+ var desc = this.master.tasks[i];
+ if (desc.level > oldLevel || desc == this) {
+ desc.level++;
+ //remove links from descendant to my parents
+ this.master.links = this.master.links.filter(function(link) {
+ var linkToParent = false;
+ if (link.to == desc)
+ linkToParent = futureParents.indexOf(link.from) >= 0;
+ else if (link.from == desc)
+ linkToParent = futureParents.indexOf(link.to) >= 0;
+ return !linkToParent;
+ });
+ } else
+ break;
+ }
+ //recompute depends string
+ this.master.updateDependsStrings();
+ //enlarge parent using a fake set period
+ this.setPeriod(this.start + 1, this.end + 1);
+
+ //force status check
+ this.synchronizeStatus();
+ }
+ return ret;
+};
+
+
+Task.prototype.outdent = function() {
+ //console.debug("outdent", this);
+
+ //a level must be >1 -> cannot escape from root
+ if (this.level <= 1)
+ return false;
+
+ var ret = false;
+ var oldLevel = this.level;
+
+ ret = true;
+ var row = this.getRow();
+ for (var i = row; i < this.master.tasks.length; i++) {
+ var desc = this.master.tasks[i];
+ if (desc.level > oldLevel || desc == this) {
+ desc.level--;
+ } else
+ break;
+ }
+
+ var task = this;
+ var chds = this.getChildren();
+ //remove links from me to my new children
+ this.master.links = this.master.links.filter(function(link) {
+ var linkExist = (link.to == task && chds.indexOf(link.from) >= 0 || link.from == task && chds.indexOf(link.to) >= 0);
+ return !linkExist;
+ });
+
+
+ //enlarge me if inherited children are larger
+ for (var i=0;i<chds.length;i++) {
+ //remove links from me to my new children
+ chds[i].setPeriod(chds[i].start + 1, chds[i].end + 1);
+ }
+
+ //enlarge parent using a fake set period
+ this.setPeriod(this.start + 1, this.end + 1);
+
+ //force status check
+ this.synchronizeStatus();
+ return ret;
+};
+
+
+//<%------------------------------------------ MOVE UP / MOVE DOWN --------------------------------%>
+Task.prototype.moveUp = function() {
+ //console.debug("moveUp", this);
+ var ret = false;
+
+ //a row above must exist
+ var row = this.getRow();
+
+ //no row no party
+ if (row <=0)
+ return false;
+
+ //find new row
+ var newRow;
+ for (newRow = row - 1; newRow >= 0; newRow--) {
+ if (this.master.tasks[newRow].level <= this.level)
+ break;
+ }
+
+ //is a parent or a brother
+ if (this.master.tasks[newRow].level == this.level) {
+ ret = true;
+ //compute descendant
+ var descNumber = 0;
+ for (var i = row + 1; i < this.master.tasks.length; i++) {
+ var desc = this.master.tasks[i];
+ if (desc.level > this.level) {
+ descNumber++;
+ } else {
+ break;
+ }
+ }
+ //move in memory
+ var blockToMove = this.master.tasks.splice(row, descNumber + 1);
+ var top = this.master.tasks.splice(0, newRow);
+ this.master.tasks = [].concat(top, blockToMove, this.master.tasks);
+ //move on dom
+ var rows = this.master.editor.element.find("tr[taskId]");
+ var domBlockToMove = rows.slice(row, row + descNumber + 1);
+ rows.eq(newRow).before(domBlockToMove);
+
+ //recompute depends string
+ this.master.updateDependsStrings();
+ } else {
+ this.master.setErrorOnTransaction(GanttMaster.messages["TASK_MOVE_INCONSISTENT_LEVEL"], this);
+ ret = false;
+ }
+ return ret;
+};
+
+
+Task.prototype.moveDown = function() {
+ //console.debug("moveDown", this);
+
+ //a row below must exist, and cannot move root task
+ var row = this.getRow();
+ if (row >= this.master.tasks.length - 1 || row==0)
+ return false;
+
+ var ret = false;
+
+ //find nearest brother
+ var newRow;
+ for (newRow = row + 1; newRow < this.master.tasks.length; newRow++) {
+ if (this.master.tasks[newRow].level <= this.level)
+ break;
+ }
+
+ //is brother
+ if (this.master.tasks[newRow].level == this.level) {
+ ret = true;
+ //find last desc
+ for (newRow = newRow + 1; newRow < this.master.tasks.length; newRow++) {
+ if (this.master.tasks[newRow].level <= this.level)
+ break;
+ }
+
+ //compute descendant
+ var descNumber = 0;
+ for (var i = row + 1; i < this.master.tasks.length; i++) {
+ var desc = this.master.tasks[i];
+ if (desc.level > this.level) {
+ descNumber++;
+ } else {
+ break;
+ }
+ }
+
+ //move in memory
+ var blockToMove = this.master.tasks.splice(row, descNumber + 1);
+ var top = this.master.tasks.splice(0, newRow - descNumber - 1);
+ this.master.tasks = [].concat(top, blockToMove, this.master.tasks);
+
+
+ //move on dom
+ var rows = this.master.editor.element.find("tr[taskId]");
+ var aft = rows.eq(newRow - 1);
+ var domBlockToMove = rows.slice(row, row + descNumber + 1);
+ aft.after(domBlockToMove);
+
+ //recompute depends string
+ this.master.updateDependsStrings();
+ }
+
+ return ret;
+};
+
+
+//<%------------------------------------------------------------------------ LINKS OBJECT ---------------------------------------------------------------%>
+function Link(taskFrom, taskTo, lagInWorkingDays) {
+ this.from = taskFrom;
+ this.to = taskTo;
+ this.lag = lagInWorkingDays;
+}
+
+
+//<%------------------------------------------------------------------------ ASSIGNMENT ---------------------------------------------------------------%>
+function Assignment(id, resourceId, roleId, effort) {
+ this.id = id;
+ this.resourceId = resourceId;
+ this.roleId = roleId;
+ this.effort = effort;
+}
+
+
+//<%------------------------------------------------------------------------ RESOURCE ---------------------------------------------------------------%>
+function Resource(id, name) {
+ this.id = id;
+ this.name = name;
+}
+
+
+//<%------------------------------------------------------------------------ ROLE ---------------------------------------------------------------%>
+function Role(id, name) {
+ this.id = id;
+ this.name = name;
+}
+
+
+
+
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttUtilities.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttUtilities.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/ganttUtilities.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,237 @@
+/*
+ Copyright (c) 2012-2013 Open Lab
+ Written by Roberto Bicchierai and Silvia Chelazzi http://roberto.open-lab.com
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+$.fn.gridify = function(options) {
+ this.options = {
+ colResizeZoneWidth:10
+ };
+
+ $.extend(this.options, options);
+ $.gridify.init($(this), this.options);
+ return this;
+};
+
+$.gridify = {
+ init: function(elems, opt) {
+ elems.each(function() {
+ var table = $(this);
+
+ //---------------------- header management start
+ table.find("th.gdfColHeader.gdfResizable:not(.gdfied)").mouseover(function() {
+ $(this).addClass("gdfColHeaderOver");
+
+ }).bind("mouseout.gdf", function() {
+ $(this).removeClass("gdfColHeaderOver");
+ if (!$.gridify.columInResize) {
+ $("body").removeClass("gdfHResizing");
+ }
+
+ }).bind("mousemove.gdf", function(e) {
+ if (!$.gridify.columInResize) {
+ var colHeader = $(this);
+ var mousePos = e.pageX - colHeader.offset().left;
+
+ if (colHeader.width() - mousePos < opt.colResizeZoneWidth) {
+ $("body").addClass("gdfHResizing");
+ } else {
+ $("body").removeClass("gdfHResizing");
+ }
+ }
+
+ }).bind("mousedown.gdf", function(e) {
+ var colHeader = $(this);
+ var mousePos = e.pageX - colHeader.offset().left;
+ if (colHeader.width() - mousePos < opt.colResizeZoneWidth) {
+ $.gridify.columInResize = $(this);
+ //bind event for start resizing
+ //console.debug("start resizing");
+ $(document).bind("mousemove.gdf", function(e) {
+ //manage resizing
+ //console.debug(e.pageX - $.gridify.columInResize.offset().left)
+ $.gridify.columInResize.width(e.pageX - $.gridify.columInResize.offset().left);
+
+
+ //bind mouse up on body to stop resizing
+ }).bind("mouseup.gdf", function() {
+ //console.debug("stop resizing");
+ $(this).unbind("mousemove.gdf").unbind("mouseup.gdf");
+ $("body").removeClass("gdfHResizing");
+ delete $.gridify.columInResize;
+ });
+ }
+ }).addClass("gdfied unselectable").attr("unselectable","true");
+
+
+ //---------------------- cell management start wrapping
+ table.find("td.gdfCell:not(.gdfied)").each(function() {
+ var cell = $(this);
+ if (cell.is(".gdfEditable")) {
+ var inp = $("<input type='text'>").addClass("gdfCellInput");
+ inp.val(cell.text());
+ cell.empty().append(inp);
+ } else {
+ var wrp = $("<div>").addClass("gdfCellWrap");
+ wrp.html(cell.html());
+ cell.empty().append(wrp);
+ }
+ }).addClass("gdfied");
+ ;
+
+ });
+ }
+};
+
+$.splittify = {
+ init: function(where, first, second,perc) {
+
+ perc=perc || 50;
+
+ var splitter = $("<div>").addClass("splitterContainer");
+
+ var firstBox = $("<div>").addClass("splitElement splitBox1");
+ var splitterBar = $("<div>").addClass("splitElement vSplitBar").attr("unselectable", "on").html("|").css("padding-top",where.height()/2+"px");
+ var secondBox = $("<div>").addClass("splitElement splitBox2");
+
+ firstBox.append(first);
+ secondBox.append(second);
+
+ splitter.append(firstBox);
+ splitter.append(secondBox);
+ splitter.append(splitterBar);
+
+
+ where.append(splitter);
+
+ var w = where.innerWidth();
+ firstBox.width(w *perc/ 100 - splitterBar.width()).css({left:0});
+ splitterBar.css({left:firstBox.width()});
+ secondBox.width(w -firstBox.width()-splitterBar.width() ).css({left:firstBox.width() + splitterBar.width()});
+
+
+
+ splitterBar.bind("mousedown.gdf", function(e) {
+ $.splittify.splitterBar = $(this);
+ //bind event for start resizing
+ //console.debug("start splitting");
+ $("body").unselectable().bind("mousemove.gdf", function(e) {
+ //manage resizing
+ //console.debug(e.pageX - $.gridify.columInResize.offset().left)
+ var sb = $.splittify.splitterBar;
+ var pos = e.pageX - sb.parent().offset().left;
+ var w = sb.parent().width();
+ if (pos > 10 && pos < w - 20) {
+ sb.css({left:pos});
+ firstBox.width(pos);
+ secondBox.css({left:pos + sb.width(),width:w - pos - sb.width()});
+ }
+
+ //bind mouse up on body to stop resizing
+ }).bind("mouseup.gdf", function() {
+ //console.debug("stop splitting");
+ $(this).unbind("mousemove.gdf").unbind("mouseup.gdf").clearUnselectable();
+ delete $.splittify.splitterBar;
+
+ });
+ });
+
+ return {firstBox:firstBox,secondBox:secondBox,splitterBar:splitterBar};
+ }
+};
+
+
+
+
+//<%------------------------------------------------------------------------ UTILITIES ---------------------------------------------------------------%>
+ function computeStart(start) {
+ var d = new Date(start+3600000*12);
+ d.setHours(0, 0, 0, 0);
+ //move to next working day
+ while (isHoliday(d)) {
+ d.setDate(d.getDate() + 1);
+ }
+ d.setHours(0, 0, 0, 0);
+ return d.getTime();
+ }
+
+ function computeEnd(end) {
+ var d = new Date(end-3600000*12);
+ d.setHours(23, 59, 59, 999);
+ //move to next working day
+ while (isHoliday(d)) {
+ d.setDate(d.getDate() + 1);
+ }
+ d.setHours(23, 59, 59, 999);
+ return d.getTime();
+ }
+
+ function computeEndByDuration(start, duration) {
+ var d = new Date(start);
+ //console.debug("computeEndByDuration start ",d,duration)
+ var q = duration - 1;
+ while (q > 0) {
+ d.setDate(d.getDate() + 1);
+ if (!isHoliday(d))
+ q--;
+ }
+ d.setHours(23, 59, 59, 999);
+ return d.getTime();
+ }
+
+ function incrementDateByWorkingDays(date, days) {
+ var d = new Date(date);
+ d.incrementDateByWorkingDays(days);
+ return d.getTime();
+ }
+
+function recomputeDuration(start, end) {
+ //console.debug("recomputeDuration");
+ return new Date(start).distanceInWorkingDays(new Date(end));
+ }
+
+
+
+//This prototype is provided by the Mozilla foundation and
+//is distributed under the MIT license.
+//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
+
+if (!Array.prototype.filter){
+ Array.prototype.filter = function(fun )
+ {
+ var len = this.length;
+ if (typeof fun != "function")
+ throw new TypeError();
+
+ var res = new Array();
+ var thisp = arguments[1];
+ for (var i = 0; i < len; i++)
+ {
+ if (i in this)
+ {
+ var val = this[i]; // in case fun mutates this
+ if (fun.call(thisp, val, i, this))
+ res.push(val);
+ }
+ }
+ return res;
+ };
+}
\ No newline at end of file
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/gantt_compact.css
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/gantt_compact.css (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/gantt_compact.css 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,323 @@
+.gdfTable {
+ table-layout: fixed;
+ border-collapse: separate;
+ border-spacing: 0;
+}
+
+.gdfTable td, .gdfTable th {
+ vertical-align: middle;
+ overflow: hidden;
+ text-overflow: clip;
+ white-space: nowrap;
+ font-size: 10px
+}
+
+.gdfCell {
+ overflow: hidden;
+ padding:1px
+}
+
+.gdfColHeader {
+ min-width: 5px;
+ height: 30px;
+}
+
+.gdfCell, .gdfColHeader {
+ border-bottom: 1px solid #eee;
+ border-right: 1px solid #eee;
+}
+
+
+.ganttLines{
+ position:absolute;
+ width:100%;
+ height:1px;
+ border-top:1px solid #eee;
+ z-index:1;
+}
+
+.gdfCellInput {
+ border: 0 none;
+ font-size: 12px;
+ height: 14px;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ background-color: #d4fbe8;
+}
+
+.gdfCellWrap {
+ border: 0 none;
+ font-size: 12px;
+ height: 14px;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ overflow: hidden;
+
+ background-color: #ffcccc;
+}
+
+.gdfColHeaderOver {
+ opacity: .7;
+}
+
+.gdfHResizing {
+ cursor: w-resize;
+}
+
+.splitterContainer {
+ width: 100%;
+ height: 100%;
+}
+
+.splitBox1, .splitBox2 {
+ overflow-x: scroll;
+ overflow-y: hidden;
+
+ /*background-color: yellow;*/
+}
+
+.splitBox2 {
+ /*background-color: orange;*/
+}
+
+.unselectable {
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+}
+
+.splitElement {
+ outline-style: none;
+ position: absolute;
+ height: 100%;
+}
+
+.vSplitBar {
+ width: 5px;
+ background-color: #aaa;
+ cursor: w-resize;
+ text-align: center;
+ color: white;
+}
+
+.end{
+ border-right:1px dotted #666
+}
+
+.holyH{
+ background-color: #9CB7AA;
+}
+.holy{
+ background-color: #FFF5E6;
+}
+
+
+.expcoll{
+ width:6px;
+ height:6px;
+ margin:1px;
+ padding:1px;
+ background-color:yellow;
+ display:inline-block;
+ border:1px solid gray;
+}
+.expcoll.exp{
+ display:none;
+}
+
+
+.ganttTable{
+ table-layout:fixed;
+}
+
+.ganttTable td,.ganttTable th{
+ overflow: hidden;
+ text-overflow: clip;
+ white-space: nowrap;
+}
+
+.ganttHead1,.ganttHead2{
+ height:20px;
+}
+
+.ganttHead1 th,.ganttHead2 th{
+ border-left:1px solid white;
+}
+
+.ganttToday{
+ position:absolute;
+ top:0;
+ width:1px;
+ height:100%;
+ border-left:2px dotted #13AFA5;
+}
+
+.ganttHighLight{
+ position:absolute;
+ width:100%;
+ height:18px;
+ background-color:yellow;
+ opacity:.4;
+}
+
+.ganttButtonBar{
+ position:relative;
+ padding:5px;
+}
+
+.ganttButtonBar .buttons {
+ float:left; margin:45px 0 0 40px
+}
+
+
+.ganttButtonBar .button span.teamworkIcon{
+ font-size: 150%
+}
+
+.ganttButtonSeparator{
+ border-left:1px solid gray;
+ padding-right:10px;
+ margin-left:10px;
+ font-size: 130%
+}
+
+.ganttLinks{
+ z-index:10;
+}
+
+.taskBox{
+ position:absolute;
+ height:18px;
+ margin-top:1px;
+ z-index:100;
+}
+
+.taskBox .layout {
+ height:100%;
+ color:red;
+ border-radius:2px;
+ background: #eee; /* Old browsers */
+ border:1px solid #bbb;
+}
+
+.taskBox .taskStatus {
+ left:5px;
+ top:4px;
+ position:absolute;
+ width:10px;
+ height:10px;
+}
+
+.taskBox .layout .milestone{
+ top:0px;
+ position:absolute;
+ width:16px;
+ background: url(milestone.png) no-repeat;
+ height:16px;
+ display:none;
+}
+.taskBox .layout .milestone.end{
+ right:0;
+}
+.taskBox .layout .milestone.active{
+ display:block;
+}
+
+.taskBox.hasChild .layout{
+ border-top:2px solid black;
+}
+
+.taskBox .taskProgress{
+ height:5px;
+ position:absolute;
+}
+
+.taskBox .layout.extDep{
+ background-image:url(hasExternalDeps.png);
+}
+
+
+.taskLabel{
+ position:absolute;
+ height:18px;
+ color:black;
+ text-align:right;
+ padding-right:5px;
+ overflow:hidden;
+ left:-200px;
+ width:195px;
+ white-space:nowrap;
+}
+
+
+.taskDepLine {
+ border: 1px solid #9999ff;
+ overflow: hidden;
+ position: absolute;
+}
+
+
+.taskEditRow,.emptyRow {
+ height:18px;
+}
+
+.taskEditRow input{
+ border: 0 none;
+ font-size: 10px;
+ height: 14px;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ font-family: Arial, sans-serif
+}
+
+.taskEditRow.rowSelected td,.taskEditRow.rowSelected input{
+ background-color:#FFFF99;
+}
+
+.taskStatusBox{
+ position:absolute;
+ width:100px;
+ height:18px;
+ border:1px solid #a0a0a0;
+ background-color:#fff;
+ margin-top:2px;
+ margin-left:-1px;
+ padding: 2px
+}
+.taskStatus{
+ width:12px;
+ height:12px;
+ display:inline-block;
+}
+.taskStatus[status=STATUS_ACTIVE]{
+ background-color: #66FF99;
+}
+.taskStatus[status=STATUS_DONE]{
+ background-color: #0099FF;
+}
+.taskStatus[status=STATUS_FAILED]{
+ background-color: #660066;
+}
+.taskStatus[status=STATUS_SUSPENDED]{
+ background-color: #fbb11e;
+}
+.taskStatus[status=STATUS_UNDEFINED]{
+ background-color: #ffffff;
+}
+.taskStatus.selected{
+ border:#666 2px solid;
+}
+
+
+.ui-resizable-helper { border: 1px dotted #00F; }
+.ui-resizable-e, .ui-resizable-w {width: 5px;}
+.ui-draggable{
+ cursor:move;
+}
+
+
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/hasExternalDeps.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/hasExternalDeps.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/JST/jquery.JST.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/JST/jquery.JST.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/JST/jquery.JST.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,167 @@
+$.fn.loadTemplates = function() {
+ $.JST.loadTemplates($(this));
+ return this;
+};
+
+$.JST = {
+ _templates: new Object(),
+ _decorators:new Object(),
+
+ loadTemplates: function(elems) {
+ elems.each(function() {
+ $(this).find(".__template__").each(function() {
+ var tmpl = $(this);
+ var type = tmpl.attr("type");
+
+ //template may be inside <!-- ... --> or not in case of ajax loaded templates
+ if (tmpl.get(0).firstChild.nodeType == 8) // 8==comment
+ var templateBody = tmpl.get(0).firstChild.nodeValue; // this is inside the comment
+ else
+ var templateBody = tmpl.html(); // this is the whole template
+
+ if (!templateBody.match(/##\w+##/)) { // is Resig' style? e.g. (#=id#) or (# ...some javascript code 'obj' is the alias for the object #)
+ var strFunc =
+ "var p=[],print=function(){p.push.apply(p,arguments);};" +
+ "with(obj){p.push('" +
+ templateBody.replace(/[\r\t\n]/g, " ")
+ .replace(/'(?=[^#]*#\))/g, "\t")
+ .split("'").join("\\'")
+ .split("\t").join("'")
+ .replace(/\(#=(.+?)#\)/g, "',$1,'")
+ .split("(#").join("');")
+ .split("#)").join("p.push('")
+ + "');}return p.join('');";
+
+ try {
+ $.JST._templates[type] = new Function("obj", strFunc);
+ } catch (e) {
+ console.error("JST error: "+type, e,strFunc);
+ }
+
+ } else { //plain template e.g. ##id##
+ try {
+ $.JST._templates[type] = templateBody;
+ } catch (e) {
+ console.error("JST error: "+type, e,templateBody);
+ }
+ }
+
+ tmpl.remove();
+
+ });
+ });
+ },
+
+ createFromTemplate: function(jsonData, template, transformToPrintable) {
+ var templates = $.JST._templates;
+
+ var jsData=new Object();
+ if (transformToPrintable){
+ for (var prop in jsonData){
+ var value = jsonData[prop];
+ if (typeof(value) == "string")
+ value = (value + "").replace(/\n/g, "<br>");
+ jsData[prop]=value;
+ }
+ } else {
+ jsData=jsonData;
+ }
+
+
+ function fillStripData(strip, data) {
+ for (var prop in data) {
+ var value = data[prop];
+
+ strip = strip.replace(new RegExp("##" + prop + "##", "gi"), value);
+ }
+ // then clean the remaining ##xxx##
+ strip = strip.replace(new RegExp("##\\w+##", "gi"), "");
+ return strip;
+ }
+
+ var stripString = "";
+ if (typeof(template) == "undefined") {
+ alert("Template is required");
+ stripString = "<div>Template is required</div>";
+
+ } else if (typeof(templates[template]) == "function") { // resig template
+ try {
+ stripString = templates[template](jsData);// create a jquery object in memory
+ } catch (e) {
+ console.error("JST error: "+template,e.message);
+ stripString = "<div> ERROR: "+template+"<br>" + e.message + "</div>";
+ }
+
+ } else {
+ stripString = templates[template]; // recover strip template
+ if (!stripString || stripString.trim() == "") {
+ console.error("No template found for type '" + template + "'");
+ return $("<div>");
+
+ } else {
+ stripString = fillStripData(stripString, jsData); //replace placeholders with data
+ }
+ }
+
+ var ret = $(stripString);// create a jquery object in memory
+ ret.attr("__template", template); // set __template attribute
+
+ //decorate the strip
+ var dec = $.JST._decorators[template];
+ if (typeof (dec) == "function")
+ dec(ret, jsData);
+
+ return ret;
+ },
+
+
+ existsTemplate: function(template) {
+ return $.JST._templates[template];
+ },
+
+ //decorate function is like function(domElement,jsonData){...}
+ loadDecorator:function(template, decorator) {
+ $.JST._decorators[template] = decorator;
+ },
+
+ getDecorator:function(template) {
+ return $.JST._decorators[template];
+ },
+
+ decorateTemplate:function(element) {
+ var dec = $.JST._decorators[element.attr("__template")];
+ if (typeof (dec) == "function")
+ dec(editor);
+ },
+
+ // asynchronous
+ ajaxLoadAsynchTemplates: function(templateUrl, callback) {
+
+ $.get(templateUrl, function(data) {
+
+ var div = $("<div>");
+ div.html(data);
+
+ $.JST.loadTemplates(div);
+
+ if (typeof(callback == "function"))
+ callback();
+ },"html");
+ },
+
+ ajaxLoadTemplates: function(templateUrl) {
+ $.ajax({
+ async:false,
+ url: templateUrl,
+ dataType: "html",
+ success: function(data) {
+ var div = $("<div>");
+ div.html(data);
+ $.JST.loadTemplates(div);
+ }
+ });
+
+ }
+
+
+};
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/date.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/date.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/date.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,584 @@
+/**
+ * Copyright (c)2005-2009 Matt Kruse (javascripttoolbox.com)
+ *
+ * Dual licensed under the MIT and GPL licenses.
+ * This basically means you can use this code however you want for
+ * free, but don't claim to have written it yourself!
+ * Donations always accepted: http://www.JavascriptToolbox.com/donate/
+ *
+ * Please do not link to the .js files on javascripttoolbox.com from
+ * your site. Copy the files locally to your server instead.
+ *
+ */
+/*
+Date functions
+
+These functions are used to parse, format, and manipulate Date objects.
+See documentation and examples at http://www.JavascriptToolbox.com/lib/date/
+
+*/
+Date.$VERSION = 1.02;
+
+// Utility function to append a 0 to single-digit numbers
+Date.LZ = function(x) {return(x<0||x>9?"":"0")+x};
+// Full month names. Change this for local month names
+Date.monthNames = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
+// Month abbreviations. Change this for local month names
+Date.monthAbbreviations = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
+// Full day names. Change this for local month names
+Date.dayNames = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
+// Day abbreviations. Change this for local month names
+Date.dayAbbreviations = new Array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
+// Used for parsing ambiguous dates like 1/2/2000 - default to preferring 'American' format meaning Jan 2.
+// Set to false to prefer 'European' format meaning Feb 1
+Date.preferAmericanFormat = true;
+
+// Set to 0=SUn for American 1=Mon for european
+Date.firstDayOfWeek = 0;
+
+//default
+Date.defaultFormat="dd/MM/yyyy";
+
+// If the getFullYear() method is not defined, create it
+if (!Date.prototype.getFullYear) {
+ Date.prototype.getFullYear = function() { var yy=this.getYear(); return (yy<1900?yy+1900:yy); } ;
+}
+
+// Parse a string and convert it to a Date object.
+// If no format is passed, try a list of common formats.
+// If string cannot be parsed, return null.
+// Avoids regular expressions to be more portable.
+Date.parseString = function(val, format) {
+ // If no format is specified, try a few common formats
+ if (typeof(format)=="undefined" || format==null || format=="") {
+ var generalFormats=new Array(Date.defaultFormat,'y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d','MMM-d','d-MMM');
+ var monthFirst=new Array('M/d/y','M-d-y','M.d.y','M/d','M-d');
+ var dateFirst =new Array('d/M/y','d-M-y','d.M.y','d/M','d-M');
+ var checkList=new Array(generalFormats,Date.preferAmericanFormat?monthFirst:dateFirst,Date.preferAmericanFormat?dateFirst:monthFirst);
+ for (var i=0; i<checkList.length; i++) {
+ var l=checkList[i];
+ for (var j=0; j<l.length; j++) {
+ var d=Date.parseString(val,l[j]);
+ if (d!=null) {
+ return d;
+ }
+ }
+ }
+ return null;
+ };
+
+ this.isInteger = function(val) {
+ for (var i=0; i < val.length; i++) {
+ if ("1234567890".indexOf(val.charAt(i))==-1) {
+ return false;
+ }
+ }
+ return true;
+ };
+ this.getInt = function(str,i,minlength,maxlength) {
+ for (var x=maxlength; x>=minlength; x--) {
+ var token=str.substring(i,i+x);
+ if (token.length < minlength) {
+ return null;
+ }
+ if (this.isInteger(token)) {
+ return token;
+ }
+ }
+ return null;
+ };
+
+
+ this.decodeShortcut=function(str){
+ var dateUpper = str.trim().toUpperCase();
+ var ret=new Date();
+ ret.clearTime();
+
+ if (["NOW","N"].indexOf(dateUpper)>=0) {
+ ret= new Date();
+
+ } else if (["TODAY","T"].indexOf(dateUpper)>=0) {
+ //do nothing
+
+ } else if (["YESTERDAY","Y"].indexOf(dateUpper)>=0) {
+ ret.setDate(ret.getDate()-1);
+
+ } else if (["TOMORROW","TO"].indexOf(dateUpper)>=0) {
+ ret.setDate(ret.getDate()+1);
+
+ } else if (["W", "TW", "WEEK", "THISWEEK", "WEEKSTART", "THISWEEKSTART"].indexOf(dateUpper)>=0) {
+ ret.setFirstDayOfThisWeek();
+
+ } else if (["LW", "LASTWEEK", "LASTWEEKSTART"].indexOf(dateUpper)>=0) {
+ ret.setFirstDayOfThisWeek();
+ ret.setDate(ret.getDate()-7);
+
+ } else if (["NW", "NEXTWEEK", "NEXTWEEKSTART"].indexOf(dateUpper)>=0) {
+ ret.setFirstDayOfThisWeek();
+ ret.setDate(ret.getDate()+7);
+
+ } else if (["M", "TM", "MONTH", "THISMONTH", "MONTHSTART", "THISMONTHSTART"].indexOf(dateUpper)>=0) {
+ ret.setDate(1);
+
+ } else if (["LM", "LASTMONTH", "LASTMONTHSTART"].indexOf(dateUpper)>=0) {
+ ret.setDate(1);
+ ret.setMonth(ret.getMonth()-1);
+
+ } else if (["NM", "NEXTMONTH", "NEXTMONTHSTART"].indexOf(dateUpper)>=0) {
+ ret.setDate(1);
+ ret.setMonth(ret.getMonth()+1);
+
+ } else if (["Q", "TQ", "QUARTER", "THISQUARTER", "QUARTERSTART", "THISQUARTERSTART"].indexOf(dateUpper)>=0) {
+ ret.setDate(1);
+ ret.setMonth(Math.floor((ret.getMonth()) / 3) * 3);
+
+ } else if (["LQ", "LASTQUARTER", "LASTQUARTERSTART"].indexOf(dateUpper)>=0) {
+ ret.setDate(1);
+ ret.setMonth(Math.floor((ret.getMonth()) / 3) * 3-3);
+
+ } else if (["NQ", "NEXTQUARTER", "NEXTQUARTERSTART"].indexOf(dateUpper)>=0) {
+ ret.setDate(1);
+ ret.setMonth(Math.floor((ret.getMonth()) / 3) * 3+3);
+
+
+ } else if (/^-?[0-9]+[DWMY]$/.test(dateUpper)) {
+ var lastOne = dateUpper.substr(dateUpper.length - 1);
+ var val = parseInt(dateUpper.substr(0, dateUpper.length - 1));
+ if (lastOne=="W")
+ ret.setDate(ret.getDate()+val*7 );
+ else if (lastOne=="M")
+ ret.setMonth(ret.getMonth()+val );
+ else if (lastOne=="Y")
+ ret.setYear(ret.getYear()+val );
+ } else {
+ ret=undefined;
+ }
+
+ return ret;
+ };
+
+ var ret=this.decodeShortcut(val);
+ if (ret)
+ return ret;
+
+ val=val+"";
+ format=format+"";
+ var i_val=0;
+ var i_format=0;
+ var c="";
+ var token="";
+ var token2="";
+ var x,y;
+ var year=new Date().getFullYear();
+ var month=1;
+ var date=1;
+ var hh=0;
+ var mm=0;
+ var ss=0;
+ var ampm="";
+ while (i_format < format.length) {
+ // Get next token from format string
+ c=format.charAt(i_format);
+ token="";
+ while ((format.charAt(i_format)==c) && (i_format < format.length)) {
+ token += format.charAt(i_format++);
+ }
+ // Extract contents of value based on format token
+ if (token=="yyyy" || token=="yy" || token=="y") {
+ if (token=="yyyy") {
+ x=4;y=4;
+ }
+ if (token=="yy") {
+ x=2;y=2;
+ }
+ if (token=="y") {
+ x=2;y=4;
+ }
+ year=this.getInt(val,i_val,x,y);
+ if (year==null) {
+ return null;
+ }
+ i_val += year.length;
+ if (year.length==2) {
+ if (year > 70) {
+ year=1900+(year-0);
+ }
+ else {
+ year=2000+(year-0);
+ }
+ }
+
+// } else if (token=="MMM" || token=="NNN"){
+ } else if (token=="MMM" || token=="MMMM"){
+ month=0;
+ var names = (token=="MMMM"?(Date.monthNames.concat(Date.monthAbbreviations)):Date.monthAbbreviations);
+ for (var i=0; i<names.length; i++) {
+ var month_name=names[i];
+ if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) {
+ month=(i%12)+1;
+ i_val += month_name.length;
+ break;
+ }
+ }
+ if ((month < 1)||(month>12)){
+ return null;
+ }
+ }
+ else if (token=="E"||token=="EE"||token=="EEE"||token=="EEEE"){
+ var names = (token=="EEEE"?Date.dayNames:Date.dayAbbreviations);
+ for (var i=0; i<names.length; i++) {
+ var day_name=names[i];
+ if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) {
+ i_val += day_name.length;
+ break;
+ }
+ }
+ }
+ else if (token=="MM"||token=="M") {
+ month=this.getInt(val,i_val,token.length,2);
+ if(month==null||(month<1)||(month>12)){
+ return null;
+ }
+ i_val+=month.length;
+ }
+ else if (token=="dd"||token=="d") {
+ date=this.getInt(val,i_val,token.length,2);
+ if(date==null||(date<1)||(date>31)){
+ return null;
+ }
+ i_val+=date.length;
+ }
+ else if (token=="hh"||token=="h") {
+ hh=this.getInt(val,i_val,token.length,2);
+ if(hh==null||(hh<1)||(hh>12)){
+ return null;
+ }
+ i_val+=hh.length;
+ }
+ else if (token=="HH"||token=="H") {
+ hh=this.getInt(val,i_val,token.length,2);
+ if(hh==null||(hh<0)||(hh>23)){
+ return null;
+ }
+ i_val+=hh.length;
+ }
+ else if (token=="KK"||token=="K") {
+ hh=this.getInt(val,i_val,token.length,2);
+ if(hh==null||(hh<0)||(hh>11)){
+ return null;
+ }
+ i_val+=hh.length;
+ hh++;
+ }
+ else if (token=="kk"||token=="k") {
+ hh=this.getInt(val,i_val,token.length,2);
+ if(hh==null||(hh<1)||(hh>24)){
+ return null;
+ }
+ i_val+=hh.length;
+ hh--;
+ }
+ else if (token=="mm"||token=="m") {
+ mm=this.getInt(val,i_val,token.length,2);
+ if(mm==null||(mm<0)||(mm>59)){
+ return null;
+ }
+ i_val+=mm.length;
+ }
+ else if (token=="ss"||token=="s") {
+ ss=this.getInt(val,i_val,token.length,2);
+ if(ss==null||(ss<0)||(ss>59)){
+ return null;
+ }
+ i_val+=ss.length;
+ }
+ else if (token=="a") {
+ if (val.substring(i_val,i_val+2).toLowerCase()=="am") {
+ ampm="AM";
+ }
+ else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {
+ ampm="PM";
+ }
+ else {
+ return null;
+ }
+ i_val+=2;
+ }
+ else {
+ if (val.substring(i_val,i_val+token.length)!=token) {
+ return null;
+ }
+ else {
+ i_val+=token.length;
+ }
+ }
+ }
+ // If there are any trailing characters left in the value, it doesn't match
+ if (i_val != val.length) {
+ return null;
+ }
+ // Is date valid for month?
+ if (month==2) {
+ // Check for leap year
+ if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
+ if (date > 29){
+ return null;
+ }
+ }
+ else {
+ if (date > 28) {
+ return null;
+ }
+ }
+ }
+ if ((month==4)||(month==6)||(month==9)||(month==11)) {
+ if (date > 30) {
+ return null;
+ }
+ }
+ // Correct hours value
+ if (hh<12 && ampm=="PM") {
+ hh=hh-0+12;
+ }
+ else if (hh>11 && ampm=="AM") {
+ hh-=12;
+ }
+ return new Date(year,month-1,date,hh,mm,ss);
+};
+
+// Check if a date string is valid
+Date.isValid = function(val,format) {
+ return (Date.parseString(val,format) != null);
+};
+
+// Check if a date object is before another date object
+Date.prototype.isBefore = function(date2) {
+ if (date2==null) {
+ return false;
+ }
+ return (this.getTime()<date2.getTime());
+};
+
+// Check if a date object is after another date object
+Date.prototype.isAfter = function(date2) {
+ if (date2==null) {
+ return false;
+ }
+ return (this.getTime()>date2.getTime());
+};
+
+// Check if two date objects have equal dates and times
+Date.prototype.equals = function(date2) {
+ if (date2==null) {
+ return false;
+ }
+ return (this.getTime()==date2.getTime());
+};
+
+// Check if two date objects have equal dates, disregarding times
+Date.prototype.equalsIgnoreTime = function(date2) {
+ if (date2==null) {
+ return false;
+ }
+ var d1 = new Date(this.getTime()).clearTime();
+ var d2 = new Date(date2.getTime()).clearTime();
+ return (d1.getTime()==d2.getTime());
+};
+
+// Format a date into a string using a given format string
+Date.prototype.format = function(format) {
+ if (!format)
+ format=Date.defaultFormat;
+ format=format+"";
+ var result="";
+ var i_format=0;
+ var c="";
+ var token="";
+ var y=this.getFullYear()+"";
+ var M=this.getMonth()+1;
+ var d=this.getDate();
+ var E=this.getDay();
+ var H=this.getHours();
+ var m=this.getMinutes();
+ var s=this.getSeconds();
+ // Convert real date parts into formatted versions
+ var value=new Object();
+ if (y.length < 4) {
+ y=""+(+y+1900);
+ }
+ value["y"]=""+y;
+ value["yyyy"]=y;
+ value["yy"]=y.substring(2,4);
+ value["M"]=M;
+ value["MM"]=Date.LZ(M);
+ value["MMM"]=Date.monthAbbreviations[M-1];
+ value["MMMM"]=Date.monthNames[M-1];
+ value["d"]=d;
+ value["dd"]=Date.LZ(d);
+ value["E"]=Date.dayAbbreviations[E];
+ value["EE"]=Date.dayAbbreviations[E];
+ value["EEE"]=Date.dayAbbreviations[E];
+ value["EEEE"]=Date.dayNames[E];
+ value["H"]=H;
+ value["HH"]=Date.LZ(H);
+ if (H==0){
+ value["h"]=12;
+ }
+ else if (H>12){
+ value["h"]=H-12;
+ }
+ else {
+ value["h"]=H;
+ }
+ value["hh"]=Date.LZ(value["h"]);
+ value["K"]=value["h"]-1;
+ value["k"]=value["H"]+1;
+ value["KK"]=Date.LZ(value["K"]);
+ value["kk"]=Date.LZ(value["k"]);
+ if (H > 11) {
+ value["a"]="PM";
+ }
+ else {
+ value["a"]="AM";
+ }
+ value["m"]=m;
+ value["mm"]=Date.LZ(m);
+ value["s"]=s;
+ value["ss"]=Date.LZ(s);
+ while (i_format < format.length) {
+ c=format.charAt(i_format);
+ token="";
+ while ((format.charAt(i_format)==c) && (i_format < format.length)) {
+ token += format.charAt(i_format++);
+ }
+ if (typeof(value[token])!="undefined") {
+ result=result + value[token];
+ }
+ else {
+ result=result + token;
+ }
+ }
+ return result;
+};
+
+// Get the full name of the day for a date
+Date.prototype.getDayName = function() {
+ return Date.dayNames[this.getDay()];
+};
+
+// Get the abbreviation of the day for a date
+Date.prototype.getDayAbbreviation = function() {
+ return Date.dayAbbreviations[this.getDay()];
+};
+
+// Get the full name of the month for a date
+Date.prototype.getMonthName = function() {
+ return Date.monthNames[this.getMonth()];
+};
+
+// Get the abbreviation of the month for a date
+Date.prototype.getMonthAbbreviation = function() {
+ return Date.monthAbbreviations[this.getMonth()];
+};
+
+// Clear all time information in a date object
+Date.prototype.clearTime = function() {
+ this.setHours(0);
+ this.setMinutes(0);
+ this.setSeconds(0);
+ this.setMilliseconds(0);
+ return this;
+};
+
+// Add an amount of time to a date. Negative numbers can be passed to subtract time.
+Date.prototype.add = function(interval, number) {
+ if (typeof(interval)=="undefined" || interval==null || typeof(number)=="undefined" || number==null) {
+ return this;
+ }
+ number = +number;
+ if (interval=='y') { // year
+ this.setFullYear(this.getFullYear()+number);
+ }
+ else if (interval=='M') { // Month
+ this.setMonth(this.getMonth()+number);
+ }
+ else if (interval=='d') { // Day
+ this.setDate(this.getDate()+number);
+ }
+ else if (interval=='w') { // Weekday
+ var step = (number>0)?1:-1;
+ while (number!=0) {
+ this.add('d',step);
+ while(this.getDay()==0 || this.getDay()==6) {
+ this.add('d',step);
+ }
+ number -= step;
+ }
+ }
+ else if (interval=='h') { // Hour
+ this.setHours(this.getHours() + number);
+ }
+ else if (interval=='m') { // Minute
+ this.setMinutes(this.getMinutes() + number);
+ }
+ else if (interval=='s') { // Second
+ this.setSeconds(this.getSeconds() + number);
+ }
+ return this;
+
+};
+
+Date.prototype.toInt = function () {
+ return this.getFullYear()*10000+(this.getMonth()+1)*100+this.getDate();
+};
+
+Date.fromInt=function (dateInt){
+ var year = parseInt(dateInt/10000);
+ var month = parseInt((dateInt-year*10000)/100);
+ var day = parseInt(dateInt-year*10000-month*100);
+ return new Date(year,month-1,day,12,00,00);
+};
+
+
+Date.prototype.isHoliday=function(){
+ return isHoliday(this);
+};
+
+Date.prototype.isToday=function(){
+ return this.toInt()==new Date().toInt();
+};
+
+
+Date.prototype.incrementDateByWorkingDays=function (days) {
+ //console.debug("incrementDateByWorkingDays start ",d,days)
+ var q = Math.abs(days);
+ while (q > 0) {
+ this.setDate(this.getDate() + (days > 0 ? 1 : -1));
+ if (!this.isHoliday())
+ q--;
+ }
+ return this;
+};
+
+
+//todo questo può essere poco performante in caso di distanze grandi
+Date.prototype.distanceInWorkingDays= function (toDate){
+ var pos = new Date(this.getTime());
+ pos.setHours(23, 59, 59, 999);
+ var days = 0;
+ var nd=new Date(toDate.getTime());
+ nd.setHours(23, 59, 59, 999);
+ var end=nd.getTime();
+ while (pos.getTime() <= end) {
+ days = days + (isHoliday(pos) ? 0 : 1);
+ pos.setDate(pos.getDate() + 1);
+ }
+ return days;
+};
+
+
+Date.prototype.setFirstDayOfThisWeek= function (firstDayOfWeek){
+ if (!firstDayOfWeek)
+ firstDayOfWeek=Date.firstDayOfWeek;
+ this.setDate(this.getDate() - this.getDay() +firstDayOfWeek - (this.getDay()==0 && firstDayOfWeek!=0 ?7:0));
+}
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/images/next.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/images/next.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/images/prev.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/images/prev.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/jquery.dateField.css
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/jquery.dateField.css (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/jquery.dateField.css 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,88 @@
+.calBox {
+ background-color: #91B4B7;
+ padding: 2px;
+ -moz-border-radius: 4px;
+ text-align: center;
+ color: white;
+ width:200px;
+ position:absolute;
+}
+
+.calElement,.calDayHeader {
+ margin: 1px;
+ display: inline-block;
+ overflow:hidden;
+}
+
+.calDayHeader {
+ background-color: #617777
+}
+
+.calNavBar {
+ padding: 5px 5px 2px 5px;
+ margin-bottom: 5px;
+}
+
+.calDay {
+}
+
+.calDay .calElement, .calDay .calDayHeader {
+ font-size: 11px;
+ border: 1px dotted #617777;
+}
+
+.calElement.prev,
+.calElement.next {
+ width: 16px;
+ height: 16px;
+ border: none;
+}
+.calElement.prev {
+ background: transparent url(images/prev.png) no-repeat 10px 0;
+ float:left;
+}
+
+.calElement.next {
+ background: transparent url(images/next.png) no-repeat;
+ float:right;
+}
+
+.calElement.next:hover, .calElement.prev:hover {
+ background-color: transparent;
+ border:none;
+ cursor: pointer;
+ opacity: 0.6
+}
+
+.calDay .calElement .dayNumber {
+ font-size: 20px;
+}
+
+.calDay.calFullMonth .dayNumber {
+ font-size: 14px;
+}
+.calDay .calOutOfScope{
+ color: #B8D4D6;
+}
+
+.calElement.selected {
+ background-color: #404040;
+ border: 1px solid #404040;
+}
+
+.calElement:hover {
+ background-color: #404040;
+ border: 1px solid #404040;
+ cursor: pointer;
+}
+
+.calElement.today {
+ background-color: #009E94;
+}
+
+.shortCuts span{
+ border: 1px solid #999999;
+ height:14px;
+ padding-left:2px;
+ padding-right:2px;
+}
\ No newline at end of file
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/jquery.dateField.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/jquery.dateField.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/dateField/jquery.dateField.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,212 @@
+/*
+ Copyright (c) 2009 Open Lab
+ Written by Roberto Bicchierai http://roberto.open-lab.com
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+jQuery.fn.dateField = function(options) {
+
+ //check if the input field is passed correctly
+ if (!options.inputField){
+ console.error("You must supply an input field");
+ return false;
+ }
+
+ // -------------------------- start default option values --------------------------
+
+ if (typeof(options.firstDayOfWeek) == "undefined")
+ options.firstDayOfWeek=Date.firstDayOfWeek;
+
+ if (typeof(options.useWheel) == "undefined")
+ options.useWheel=true;
+
+ if (typeof(options.dateFormat) == "undefined")
+ options.dateFormat=Date.defaultFormat;
+ // -------------------------- end default option values --------------------------
+
+
+ // ------------------ start
+ if(options.inputField.is("[readonly]") || options.inputField.is("[disabled]"))
+ return;
+
+ var calendar = {currentDate: new Date()};
+ calendar.options = options;
+
+ //build the calendar on the first element in the set of matched elements.
+ var theOpener = this.eq(0);
+ var theDiv=$("<div>").addClass("calBox");
+
+
+ //create calendar elements elements
+ var divNavBar = $("<div>").addClass("calNavBar");
+ var divDays = $("<div>").addClass("calDay");
+
+ divDays.addClass("calFullMonth");
+ theDiv.append(divNavBar).append(divDays);
+
+ if (options.isSearchField){
+ var divShortcuts=$("<div>").addClass("shortCuts").html("<span title='last quarter'>LQ</span> <span title='last month'>LM</span> <span title='this month'>M</span> <span title='last week'>LW</span> <span title='this week'>W</span> <span title='yesterday'>Y</span> <span title='today'>T</span><span title='tomorrow'>TM</span> <span title='next week'>NW</span> <span title='next month'>NM</span> <span title='this quarter'>Q</span> <span title='next quarter'>NQ</span>");
+ divShortcuts.click(function(ev){
+ var el=$(ev.target);
+ if(el.is("span")){
+ if (!options.isSearchField)
+ options.inputField.val(Date.parseString(el.text().trim(),options.dateFormat).format(options.dateFormat));
+ else
+ options.inputField.val(el.text().trim());
+ theDiv.remove();
+ }
+ });
+ theDiv.append(divShortcuts);
+ }
+
+
+ $("body").append(theDiv);
+ nearBestPosition(theOpener,theDiv);
+ theDiv.bringToFront();
+
+
+ //register for click outside. Delayed to avoid it run immediately
+ $("body").oneTime(100, "regclibodcal", function() {
+ $("body").bind("click.dateField", function() {
+ $(this).unbind("click.dateField");
+ theDiv.remove();
+ });
+ });
+
+
+ calendar.drawCalendar = function(date) {
+ calendar.currentDate = date;
+
+ var fillNavBar = function(date) {
+ var t = new Date(date.getTime());
+ divNavBar.empty();
+
+ t.setMonth(t.getMonth()-1);
+ var spanPrev = $("<span>").addClass("calElement noCallback prev").attr("millis", t.getTime());
+ t.setMonth(t.getMonth()+1);
+ var spanMonth = $("<span>").html(t.format("MMMM yyyy"));
+ t.setMonth(t.getMonth()+1);
+ var spanNext = $("<span>").addClass("calElement noCallback next").attr("millis", t.getTime());
+
+ divNavBar.append(spanPrev).append(spanMonth).append(spanNext);
+ };
+
+ var fillDaysFullMonth = function(date) {
+ divDays.empty();
+ var t = new Date();//today
+ var w = parseInt((theDiv.width()-4-(4*7))/7)+"px";
+ // draw day headers
+ var d = new Date(date);
+ d.setFirstDayOfThisWeek(options.firstDayOfWeek);
+ for (var i = 0; i < 7; i++) {
+ var span = $("<span>").addClass("calDayHeader").attr("day", d.getDay());
+ span.css("width",w);
+ span.html(Date.dayAbbreviations[d.getDay()]);
+
+ //call the dayHeaderRenderer
+ if (typeof(options.dayHeaderRenderer) == "function")
+ options.dayHeaderRenderer(span,d.getDay());
+
+ divDays.append(span);
+ d.setDate(d.getDate()+1);
+ }
+
+ //draw cells
+ d = new Date(date);
+ d.setDate(1); // set day to start of month
+ d.setFirstDayOfThisWeek(options.firstDayOfWeek);//go to first day of week
+
+ var i=0;
+
+ while ((d.getMonth()<=date.getMonth() && d.getFullYear()<=date.getFullYear()) || d.getFullYear()<date.getFullYear() || (i%7!=0)) {
+ var span = $("<span>").addClass("calElement day").attr("millis", d.getTime());
+
+ span.html("<span class=dayNumber>" + d.getDate() + "</span>").css("width",w);
+ if (d.getYear() == t.getYear() && d.getMonth() == t.getMonth() && d.getDate() == t.getDate())
+ span.addClass("today");
+ if (d.getYear() == date.getYear() && d.getMonth() == date.getMonth() && d.getDate() == date.getDate())
+ span.addClass("selected");
+
+ if(d.getMonth()!=date.getMonth())
+ span.addClass("calOutOfScope");
+
+ //call the dayRenderer
+ if (typeof(options.dayRenderer) == "function")
+ options.dayRenderer(span,d);
+
+ divDays.append(span);
+ d.setDate(d.getDate()+1);
+ i++;
+ }
+
+ };
+
+ fillNavBar(date);
+ fillDaysFullMonth(date);
+ };
+
+
+ theDiv.click(function(ev) {
+ var el = $(ev.target).closest(".calElement");
+ if (el.size() > 0) {
+ var date = new Date(parseInt(el.attr("millis")));
+ if (el.hasClass("day")) {
+ theDiv.remove();
+ if (!el.is(".noCallback")) {
+ options.inputField.val(date.format(options.dateFormat)).attr("millis", date.getTime()).focus();
+ if (typeof(options.callback) == "function")
+ options.callback(date);
+ }
+ } else {
+ calendar.drawCalendar(date);
+ }
+ }
+ ev.stopPropagation();
+ });
+
+
+ //if mousewheel
+ if ($.event.special.mousewheel && options.useWheel) {
+ divDays.mousewheel(function(event, delta) {
+ var d = new Date(calendar.currentDate.getTime());
+ d.setMonth(d.getMonth() + delta);
+ calendar.drawCalendar(d);
+ return false;
+ });
+ }
+
+
+ // start calendar to the date in the input
+ var dateStr=options.inputField.val();
+
+
+ if (!dateStr || !Date.isValid(dateStr,options.dateFormat)){
+ calendar.drawCalendar(new Date());
+ } else {
+ var date = Date.parseString(dateStr,options.dateFormat);
+ //set date string formatted
+ if (!options.isSearchField)
+ options.inputField.val(date.format(options.dateFormat)).attr("millis",date.getTime());
+
+ calendar.drawCalendar(date);
+ }
+
+ return calendar;
+};
\ No newline at end of file
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/i18nJs.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/i18nJs.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/i18nJs.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,140 @@
+
+
+
+ function dateToRelative(localTime){
+ var diff=new Date().getTime()-localTime;
+ var ret="";
+
+ var min=60000;
+ var hour=3600000;
+ var day=86400000;
+ var wee=604800000;
+ var mon=2629800000;
+ var yea=31557600000;
+
+ if (diff<-yea*2)
+ ret ="in ## years".replace("##",(-diff/yea).toFixed(0));
+
+ else if (diff<-mon*9)
+ ret ="in ## months".replace("##",(-diff/mon).toFixed(0));
+
+ else if (diff<-wee*5)
+ ret ="in ## weeks".replace("##",(-diff/wee).toFixed(0));
+
+ else if (diff<-day*2)
+ ret ="in ## days".replace("##",(-diff/day).toFixed(0));
+
+ else if (diff<-hour)
+ ret ="in ## hours".replace("##",(-diff/hour).toFixed(0));
+
+ else if (diff<-min*35)
+ ret ="in about one hour";
+
+ else if (diff<-min*25)
+ ret ="in about half hour";
+
+ else if (diff<-min*10)
+ ret ="in some minutes";
+
+ else if (diff<-min*2)
+ ret ="in few minutes";
+
+ else if (diff<=min)
+ ret ="just now";
+
+ else if (diff<=min*5)
+ ret ="few minutes ago";
+
+ else if (diff<=min*15)
+ ret ="some minutes ago";
+
+ else if (diff<=min*35)
+ ret ="about half hour ago";
+
+ else if (diff<=min*75)
+ ret ="about an hour ago";
+
+ else if (diff<=hour*5)
+ ret ="few hours ago";
+
+ else if (diff<=hour*24)
+ ret ="## hours ago".replace("##",(diff/hour).toFixed(0));
+
+ else if (diff<=day*7)
+ ret ="## days ago".replace("##",(diff/day).toFixed(0));
+
+ else if (diff<=wee*5)
+ ret ="## weeks ago".replace("##",(diff/wee).toFixed(0));
+
+ else if (diff<=mon*12)
+ ret ="## months ago".replace("##",(diff/mon).toFixed(0));
+
+ else
+ ret ="## years ago".replace("##",(diff/yea).toFixed(0));
+
+ return ret;
+ }
+
+ //override date format i18n
+
+ Date.monthNames = ["January","February","March","April","May","June","July","August","September","October","November","December"];
+ // Month abbreviations. Change this for local month names
+ Date.monthAbbreviations = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
+ // Full day names. Change this for local month names
+ Date.dayNames =["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
+ // Day abbreviations. Change this for local month names
+ Date.dayAbbreviations = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
+ // Used for parsing ambiguous dates like 1/2/2000 - default to preferring 'American' format meaning Jan 2.
+ // Set to false to prefer 'European' format meaning Feb 1
+ Date.preferAmericanFormat = false;
+
+ Date.firstDayOfWeek =1;
+ Date.defaultFormat = "dd/MM/yyyy";
+
+
+ Number.decimalSeparator = ".";
+ Number.groupingSeparator = ",";
+ Number.minusSign = "-";
+ Number.currencyFormat = "##0.00";
+
+
+
+ var millisInWorkingDay =36000000;
+ var workingDaysPerWeek =5;
+
+ function isHoliday(date) {
+ var friIsHoly =false;
+ var satIsHoly =true;
+ var sunIsHoly =true;
+
+ pad = function (val) {
+ val = "0" + val;
+ return val.substr(val.length - 2);
+ };
+
+ var holidays = "#01_01#04_25#08_15#11_01#12_25#12_26#06_02#12_08#05_01#2010_04_05#2010_10_19#2010_05_15#2011_04_04#";
+
+ var ymd = "#" + date.getFullYear() + "_" + pad(date.getMonth() + 1) + "_" + pad(date.getDate()) + "#";
+ var md = "#" + pad(date.getMonth() + 1) + "_" + pad(date.getDate()) + "#";
+ var day = date.getDay();
+
+ return (day == 5 && friIsHoly) || (day == 6 && satIsHoly) || (day == 0 && sunIsHoly) || holidays.indexOf(ymd) > -1 || holidays.indexOf(md) > -1;
+ }
+
+
+
+ var i18n = {
+ FORM_IS_CHANGED:"You have some unsaved data on the page!",
+ YES:"yes",
+ NO:"no",
+ FLD_CONFIRM_DELETE:"confirm the deletion?",
+ INVALID_DATA:"The data inserted are invalid for the field format.",
+ ERROR_ON_FIELD:"Error on field",
+ CLOSE_ALL_CONTAINERS:"close all?",
+
+
+
+ DO_YOU_CONFIRM:"Do you confirm?"
+ };
+
+
\ No newline at end of file
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/jquery.livequery.min.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/jquery.livequery.min.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/jquery.livequery.min.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,11 @@
+/* Copyright (c) 2007 Brandon Aaron (brandon.aaron(a)gmail.com || http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * Version: 1.0.2
+ * Requires jQuery 1.1.3+
+ * Docs: http://docs.jquery.com/Plugins/livequery
+ */
+(function($){$.extend($.fn,{livequery:function(type,fn,fn2){var self=this,q;if($.isFunction(type))fn2=fn,fn=type,type=undefined;$.each($.livequery.queries,function(i,query){if(self.selector==query.selector&&self.context==query.context&&type==query.type&&(!fn||fn.$lqguid==query.fn.$lqguid)&&(!fn2||fn2.$lqguid==query.fn2.$lqguid))return(q=query)&&false;});q=q||new $.livequery(this.selector,this.context,type,fn,fn2);q.stopped=false;$.livequery.run(q.id);return this;},expire:function(type,fn,fn2){var self=this;if($.isFunction(type))fn2=fn,fn=type,type=undefined;$.each($.livequery.queries,function(i,query){if(self.selector==query.selector&&self.context==query.context&&(!type||type==query.type)&&(!fn||fn.$lqguid==query.fn.$lqguid)&&(!fn2||fn2.$lqguid==query.fn2.$lqguid)&&!this.stopped)$.livequery.stop(query.id);});return this;}});$.livequery=function(selector,context,type,fn,fn2){this.selector=selector;this.context=context||document;this.type=type;this.fn=fn;this.fn2=fn2;this.elements=[];this.stopped=false;this.id=$.livequery.queries.push(this)-1;fn.$lqguid=fn.$lqguid||$.livequery.guid++;if(fn2)fn2.$lqguid=fn2.$lqguid||$.livequery.guid++;return this;};$.livequery.prototype={stop:function(){var query=this;if(this.type)this.elements.unbind(this.type,this.fn);else if(this.fn2)this.elements.each(function(i,el){query.fn2.apply(el);});this.elements=[];this.stopped=true;},run:function(){if(this.stopped)return;var query=this;var oEls=this.elements,els=$(this.selector,this.context),nEls=els.not(oEls);this.elements=els;if(this.type){nEls.bind(this.type,this.fn);if(oEls.length>0)$.each(oEls,function(i,el){if($.inArray(el,els)<0)$.event.remove(el,query.type,query.fn);});}else{nEls.each(function(){query.fn.apply(this);});if(this.fn2&&oEls.length>0)$.each(oEls,function(i,el){if($.inArray(el,els)<0)query.fn2.apply(el);});}}};$.extend($.livequery,{guid:0,queries:[],queue:[],running:false,timeout:null,checkQueue:function(){if($.livequery.running&&$.livequery.queue.length){var length=$.livequery.queue.length;while(length--)$.livequery.queries[$.livequery.queue.shift()].run();}},pause:function(){$.livequery.running=false;},play:function(){$.livequery.running=true;$.livequery.run();},registerPlugin:function(){$.each(arguments,function(i,n){if(!$.fn[n])return;var old=$.fn[n];$.fn[n]=function(){var r=old.apply(this,arguments);$.livequery.run();return r;}});},run:function(id){if(id!=undefined){if($.inArray(id,$.livequery.queue)<0)$.livequery.queue.push(id);}else
+$.each($.livequery.queries,function(id){if($.inArray(id,$.livequery.queue)<0)$.livequery.queue.push(id);});if($.livequery.timeout)clearTimeout($.livequery.timeout);$.livequery.timeout=setTimeout($.livequery.checkQueue,20);},stop:function(id){if(id!=undefined)$.livequery.queries[id].stop();else
+$.each($.livequery.queries,function(id){$.livequery.queries[id].stop();});}});$.livequery.registerPlugin('append','prepend','after','before','wrap','attr','removeAttr','addClass','removeClass','toggleClass','empty','remove');$(function(){$.livequery.play();});var init=$.prototype.init;$.prototype.init=function(a,c){var r=init.apply(this,arguments);if(a&&a.selector)r.context=a.context,r.selector=a.selector;if(typeof a=='string')r.context=c||document,r.selector=a;return r;};$.prototype.init.prototype=$.prototype;})(jQuery);
\ No newline at end of file
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/jquery.timers.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/jquery.timers.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/jquery.timers.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,142 @@
+jQuery.fn.extend({
+ everyTime: function(interval, label, fn, times, belay) {
+ return this.each(function() {
+ jQuery.timer.add(this, interval, label, fn, times, belay);
+ });
+ },
+ oneTime: function(interval, label, fn) {
+ return this.each(function() {
+ jQuery.timer.add(this, interval, label, fn, 1);
+ });
+ },
+ stopTime: function(label, fn) {
+ return this.each(function() {
+ jQuery.timer.remove(this, label, fn);
+ });
+ }
+});
+
+jQuery.extend({
+ timer: {
+ guid: 1,
+ global: {},
+ regex: /^([0-9]+)\s*(.*s)?$/,
+ powers: {
+ // Yeah this is major overkill...
+ 'ms': 1,
+ 'cs': 10,
+ 'ds': 100,
+ 's': 1000,
+ 'das': 10000,
+ 'hs': 100000,
+ 'ks': 1000000
+ },
+ timeParse: function(value) {
+ if (value == undefined || value == null)
+ return null;
+ var result = this.regex.exec(jQuery.trim(value.toString()));
+ if (result[2]) {
+ var num = parseInt(result[1], 10);
+ var mult = this.powers[result[2]] || 1;
+ return num * mult;
+ } else {
+ return value;
+ }
+ },
+ add: function(element, interval, label, fn, times, belay) {
+ var counter = 0;
+
+ if (jQuery.isFunction(label)) {
+ if (!times)
+ times = fn;
+ fn = label;
+ label = interval;
+ }
+
+ interval = jQuery.timer.timeParse(interval);
+
+ if (typeof interval != 'number' || isNaN(interval) || interval <= 0)
+ return;
+
+ if (times && times.constructor != Number) {
+ belay = !!times;
+ times = 0;
+ }
+
+ times = times || 0;
+ belay = belay || false;
+
+ if (!element.$timers)
+ element.$timers = {};
+
+ if (!element.$timers[label])
+ element.$timers[label] = {};
+
+ fn.$timerID = fn.$timerID || this.guid++;
+
+ var handler = function() {
+ if (belay && this.inProgress)
+ return;
+ this.inProgress = true;
+ if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
+ jQuery.timer.remove(element, label, fn);
+ this.inProgress = false;
+ };
+
+ handler.$timerID = fn.$timerID;
+
+ if (!element.$timers[label][fn.$timerID])
+ element.$timers[label][fn.$timerID] = window.setInterval(handler,interval);
+
+ if ( !this.global[label] )
+ this.global[label] = [];
+ this.global[label].push( element );
+
+ },
+ remove: function(element, label, fn) {
+ var timers = element.$timers, ret;
+
+ if ( timers ) {
+
+ if (!label) {
+ for ( label in timers )
+ this.remove(element, label, fn);
+ } else if ( timers[label] ) {
+ if ( fn ) {
+ if ( fn.$timerID ) {
+ window.clearInterval(timers[label][fn.$timerID]);
+ delete timers[label][fn.$timerID];
+ }
+ } else {
+ for ( var fn in timers[label] ) {
+ window.clearInterval(timers[label][fn]);
+ delete timers[label][fn];
+ }
+ }
+
+ for ( ret in timers[label] ) break;
+ if ( !ret ) {
+ ret = null;
+ delete timers[label];
+ }
+ }
+
+ for ( ret in timers ) break;
+ if ( !ret )
+ element.$timers = null;
+ }
+ }
+ }
+});
+
+if (jQuery.browser.msie)
+ jQuery(window).one("unload", function() {
+ var global = jQuery.timer.global;
+ for ( var label in global ) {
+ var els = global[label], i = els.length;
+ while ( --i )
+ jQuery.timer.remove(els[i], label);
+ }
+ });
+
+
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/platform.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/platform.js (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/libs/platform.js 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,954 @@
+
+if(!window.console) {
+ window.console = new function() {
+ this.log = function(str) {/*alert(str)*/};
+ this.debug = function(str) {/*alert(str)*/};
+ this.error = function(str) {/*alert(str)*/};
+ };
+}
+if(!window.console.debug || !window.console.error|| !window.console.log ) {
+ window.console = new function() {
+ this.log = function(str) {/*alert(str)*/};
+ this.debug = function(str) {/*alert(str)*/};
+ this.error = function(str) {/*alert(str)*/};
+ };
+}
+
+
+//----------------------------------positioning-----------------------------------------------
+$.fn.bringToFront=function(selector){
+ var zi=10;
+ var elements = selector ? $(selector) : $("*");
+ elements.each(function() {
+ if($(this).css("position")!="static"){
+ var cur = parseInt($(this).css('zIndex'));
+ zi = cur > zi ? parseInt($(this).css('zIndex')) : zi;
+ }
+ });
+
+ return $(this).css('zIndex',zi+=10);
+};
+
+function nearBestPosition(whereId, theObjId, centerOnEl) {
+ var el=whereId;
+ var target=theObjId;
+
+ if (typeof whereId != "object"){ el = $("#"+whereId); }
+ if (typeof theObjId != "object"){target = $("#"+theObjId);}
+
+ if (el) {
+ target.css("visibility","hidden");
+ var hasContainment = false;
+
+ target.parents().each(function(){
+ if($(this).css("position")=="static")
+ return;
+ hasContainment = true;
+
+ });
+
+ var trueX = hasContainment ? el.position().left : el.offset().left;
+ var trueY = hasContainment ? el.position().top : el.offset().top;
+ var h = el.outerHeight();
+ var elHeight = parseFloat(h);
+
+ if (centerOnEl){
+ var elWidth = parseFloat(el.outerWidth());
+ var targetWidth = parseFloat(target.outerWidth());
+ trueX+=(elWidth-targetWidth)/2;
+ }
+
+ trueY += parseFloat(elHeight);
+
+ var left = trueX;
+ var top = trueY;
+ var barHeight = ($.browser.msie) ? 45 : 35;
+ var barWidth = ($.browser.msie) ? 20 : 0;
+
+ if (trueX && trueY) {
+ target.css("left", left);
+ target.css("top", top);
+ }
+
+ if (target.offset().left >= ($(window).width() - target.outerWidth())) {
+ left = ($(window).width() - target.outerWidth() - barWidth )+ "px";
+ target.css("left", left);
+ }
+
+ if (target.offset().left < 0) {
+ left = 0+ "px";
+ target.css("left", left);
+ }
+
+ if ((target.offset().top + target.outerHeight() >= (($(window).height() - barHeight))) && (target.outerHeight() < $(window).height())) {
+ target.css("margin-top",(-(el.outerHeight() + target.outerHeight())) + "px");
+ }
+
+ target.css("visibility","visible");
+ }
+}
+
+
+String.prototype.trim = function () {
+ return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1");
+};
+
+String.prototype.startsWith = function(t, i) {
+ if (!i) {
+ return (t == this.substring(0, t.length));
+ } else {
+ return (t.toLowerCase()== this.substring(0, t.length).toLowerCase());
+ }
+};
+
+String.prototype.endsWith = function(t, i) {
+ if (!i) {
+ return (t== this.substring(this.length - t.length));
+ } else {
+ return (t.toLowerCase() == this.substring(this.length -t.length).toLowerCase());
+ }
+};
+
+// leaves only char from A to Z, numbers, _ -> valid ID
+String.prototype.asId = function () {
+ return this.replace(/[^a-zA-Z0-9_]+/g, '');
+};
+
+String.prototype.replaceAll= function(from, to){
+ return this.replace(new RegExp(RegExp.quote(from), 'g'),to);
+};
+
+
+if (!Array.prototype.indexOf) {
+ Array.prototype.indexOf = function (searchElement, fromIndex) {
+ if (this == null) {
+ throw new TypeError();
+ }
+ var t = Object(this);
+ var len = t.length >>> 0;
+ if (len === 0) {
+ return -1;
+ }
+ var n = 0;
+ if (arguments.length > 0) {
+ n = Number(arguments[1]);
+ if (n != n) { // shortcut for verifying if it's NaN
+ n = 0;
+ } else if (n != 0 && n != Infinity && n != -Infinity) {
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
+ }
+ }
+ if (n >= len) {
+ return -1;
+ }
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
+ for (; k < len; k++) {
+ if (k in t && t[k] === searchElement) {
+ return k;
+ }
+ }
+ return -1;
+ };
+}
+
+
+Object.size = function(obj) {
+ var size = 0, key;
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) size++;
+ }
+ return size;
+};
+
+
+// transform string values to printable: \n in <br>
+function transformToPrintable(data){
+ for (var prop in data) {
+ var value = data[prop];
+ if (typeof(value)=="string")
+ data[prop]=(value + "").replace(/\n/g, "<br>");
+ }
+ return data;
+}
+
+
+/* Types Function */
+
+function isValidURL(url){
+ var RegExp = /^(([\w]+:)?\/\/)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(\/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?$/;
+ return RegExp.test(url);
+}
+
+function isValidEmail(email){
+ var RegExp = /^((([a-z]|[0-9]|!|#|$|%|&|'|\*|\+|\-|\/|=|\?|\^|_|`|\{|\||\}|~)+(\.([a-z]|[0-9]|!|#|$|%|&|'|\*|\+|\-|\/|=|\?|\^|_|`|\{|\||\}|~)+)*)@((((([a-z]|[0-9])([a-z]|[0-9]|\-){0,61}([a-z]|[0-9])\.))*([a-z]|[0-9])([a-z]|[0-9]|\-){0,61}([a-z]|[0-9])\.)[\w]{2,4}|(((([0-9]){1,3}\.){3}([0-9]){1,3}))|(\[((([0-9]){1,3}\.){3}([0-9]){1,3})\])))$/;
+ return RegExp.test(email);
+}
+
+function isValidInteger(n) {
+ reg = new RegExp("^[-+]{0,1}[0-9]*$");
+ return reg.test(n);
+}
+
+function isValidDouble(n) {
+ var sep = Number.decimalSeparator;
+ reg = new RegExp("^[-+]{0,1}[0-9]*[" + sep + "]{0,1}[0-9]*$");
+ return reg.test(n);
+}
+
+function isValidTime(n) {
+ return !isNaN(millisFromHourMinute(n));
+}
+
+function isValidDurationDays(n) {
+ return !isNaN(daysFromString(n));
+}
+
+function isValidDurationMillis(n) {
+ return !isNaN(millisFromString(n));
+}
+
+function isValidDurationMillis(n) {
+ return !isNaN(millisFromString(n));
+}
+
+
+/*
+ supports almost all Java currency format e.g.: ###,##0.00EUR €#,###.00 #,###.00€ -$#,###.00 $-#,###.00
+ */
+function isValidCurrency(numStr){
+ //first try to convert format in a regex
+ var regex="";
+ var format=Number.currencyFormat+"";
+
+ var minusFound=false;
+ var numFound=false;
+ var currencyString="";
+ var numberRegex="[0-9\\"+Number.groupingSeparator+"]+[\\"+Number.decimalSeparator+"]?[0-9]*";
+
+ for (var i=0; i<format.length; i++){
+ var ch= format.charAt(i);
+
+ if (ch=="." || ch=="," || ch=="0"){
+ //skip it
+ if(currencyString!=""){
+ regex=regex+"(?:"+RegExp.quote(currencyString)+")?";
+ currencyString="";
+ }
+
+ } else if (ch=="#") {
+ if(currencyString!=""){
+ regex=regex+"(?:"+RegExp.quote(currencyString)+")?";
+ currencyString="";
+ }
+
+ if (!numFound){
+ numFound=true;
+ regex=regex+numberRegex;
+ }
+
+ } else if (ch=="-"){
+ if(currencyString!=""){
+ regex=regex+"(?:"+RegExp.quote(currencyString)+")?";
+ currencyString="";
+ }
+ if (!minusFound){
+ minusFound=true;
+ regex=regex+ "[-]?";
+ }
+
+ } else {
+ currencyString=currencyString+ch;
+ }
+ }
+ if (!minusFound)
+ regex="[-]?"+regex;
+
+ if(currencyString!="")
+ regex=regex+"(?:"+RegExp.quote(currencyString)+")?";
+
+ regex="^"+regex+"$";
+
+ var rg=new RegExp(regex);
+ return rg.test(numStr);
+}
+
+function getCurrencyValue(numStr){
+ if (!isValidCurrency(numStr))
+ return NaN;
+
+ return parseFloat(numStr.replaceAll(Number.groupingSeparator,"").replaceAll(Number.decimalSeparator,".").replace(/[^0123456789.]/,""));
+}
+
+
+function formatCurrency(numberString) {
+ return formatNumber(numberString, Number.currencyFormat);
+}
+
+
+function formatNumber(numberString, format) {
+ if (!format)
+ format="##0.00";
+
+ var dec = Number.decimalSeparator;
+ var group = Number.groupingSeparator;
+ var neg = Number.minusSign;
+
+ var round = true;
+
+ var validFormat = "0#-,.";
+
+ // strip all the invalid characters at the beginning and the end
+ // of the format, and we'll stick them back on at the end
+ // make a special case for the negative sign "-" though, so
+ // we can have formats like -$23.32
+ var prefix = "";
+ var negativeInFront = false;
+ for (var i = 0; i < format.length; i++) {
+ if (validFormat.indexOf(format.charAt(i)) == -1) {
+ prefix = prefix + format.charAt(i);
+ } else {
+ if (i == 0 && format.charAt(i) == '-') {
+ negativeInFront = true;
+ } else {
+ break;
+ }
+ }
+ }
+ var suffix = "";
+ for (var i = format.length - 1; i >= 0; i--) {
+ if (validFormat.indexOf(format.charAt(i)) == -1)
+ suffix = format.charAt(i) + suffix;
+ else
+ break;
+ }
+
+ format = format.substring(prefix.length);
+ format = format.substring(0, format.length - suffix.length);
+
+ // now we need to convert it into a number
+ //while (numberString.indexOf(group) > -1)
+ // numberString = numberString.replace(group, '');
+ //var number = new Number(numberString.replace(dec, ".").replace(neg, "-"));
+ var number = new Number(numberString);
+
+
+ var forcedToZero = false;
+ if (isNaN(number)) {
+ number = 0;
+ forcedToZero = true;
+ }
+
+ // special case for percentages
+ if (suffix == "%")
+ number = number * 100;
+
+ var returnString = "";
+ if (format.indexOf(".") > -1) {
+ var decimalPortion = dec;
+ var decimalFormat = format.substring(format.lastIndexOf(".") + 1);
+
+ // round or truncate number as needed
+ if (round)
+ number = new Number(number.toFixed(decimalFormat.length));
+ else {
+ var numStr = number.toString();
+ numStr = numStr.substring(0, numStr.lastIndexOf('.') + decimalFormat.length + 1);
+ number = new Number(numStr);
+ }
+
+ var decimalValue = number % 1;
+ var decimalString = new String(decimalValue.toFixed(decimalFormat.length));
+ decimalString = decimalString.substring(decimalString.lastIndexOf(".") + 1);
+
+ for (var i = 0; i < decimalFormat.length; i++) {
+ if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) != '0') {
+ decimalPortion += decimalString.charAt(i);
+ } else if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) == '0') {
+ var notParsed = decimalString.substring(i);
+ if (notParsed.match('[1-9]')) {
+ decimalPortion += decimalString.charAt(i);
+ } else{
+ break;
+ }
+ } else if (decimalFormat.charAt(i) == "0"){
+ decimalPortion += decimalString.charAt(i);
+ }
+ }
+ returnString += decimalPortion;
+ } else{
+ number = Math.round(number);
+ }
+ var ones = Math.floor(number);
+ if (number < 0)
+ ones = Math.ceil(number);
+
+ var onesFormat = "";
+ if (format.indexOf(".") == -1)
+ onesFormat = format;
+ else
+ onesFormat = format.substring(0, format.indexOf("."));
+
+ var onePortion = "";
+ if (!(ones == 0 && onesFormat.substr(onesFormat.length - 1) == '#') || forcedToZero) {
+ // find how many digits are in the group
+ var oneText = new String(Math.abs(ones));
+ var groupLength = 9999;
+ if (onesFormat.lastIndexOf(",") != -1)
+ groupLength = onesFormat.length - onesFormat.lastIndexOf(",") - 1;
+ var groupCount = 0;
+ for (var i = oneText.length - 1; i > -1; i--) {
+ onePortion = oneText.charAt(i) + onePortion;
+ groupCount++;
+ if (groupCount == groupLength && i != 0) {
+ onePortion = group + onePortion;
+ groupCount = 0;
+ }
+ }
+
+ // account for any pre-data padding
+ if (onesFormat.length > onePortion.length) {
+ var padStart = onesFormat.indexOf('0');
+ if (padStart != -1) {
+ var padLen = onesFormat.length - padStart;
+
+ // pad to left with 0's or group char
+ var pos = onesFormat.length - onePortion.length - 1;
+ while (onePortion.length < padLen) {
+ var padChar = onesFormat.charAt(pos);
+ // replace with real group char if needed
+ if (padChar == ',')
+ padChar = group;
+ onePortion = padChar + onePortion;
+ pos--;
+ }
+ }
+ }
+ }
+
+ if (!onePortion && onesFormat.indexOf('0', onesFormat.length - 1) !== -1)
+ onePortion = '0';
+
+ returnString = onePortion + returnString;
+
+ // handle special case where negative is in front of the invalid characters
+ if (number < 0 && negativeInFront && prefix.length > 0)
+ prefix = neg + prefix;
+ else if (number < 0)
+ returnString = neg + returnString;
+
+ if (returnString.lastIndexOf(dec) == returnString.length - 1) {
+ returnString = returnString.substring(0, returnString.length - 1);
+ }
+ returnString = prefix + returnString + suffix;
+ return returnString;
+}
+
+
+
+
+RegExp.quote = function(str) {
+ return str.replace(/([.?*+^$[\]\\(){}-])/g, "\\$1");
+};
+
+/* ----- millis format --------- */
+/**
+ * @param str - Striga da riempire
+ * @param len - Numero totale di caratteri, comprensivo degli "zeri"
+ * @param ch - Carattere usato per riempire
+ */
+function pad(str, len, ch){
+ if ((str+"").length<len){
+ return new Array(len-(''+str).length+1).join(ch) + str;
+ } else{
+ return str
+ }
+}
+
+function getMillisInHours(millis) {
+ if (!millis)
+ return "";
+ var sgn=millis>=0?1:-1;
+ var hour = Math.floor(millis / 3600000);
+ return (sgn>0?"":"-")+pad(hour,2,"0");
+}
+function getMillisInHoursMinutes(millis) {
+ if (typeof(millis)!="number" )
+ return "";
+
+ var sgn=millis>=0?1:-1;
+ millis=Math.abs(millis);
+ var hour = Math.floor(millis / 3600000);
+ var min = Math.floor((millis % 3600000) / 60000);
+ return (sgn>0?"":"-")+pad(hour,1,"0") + ":" + pad(min,2,"0");
+}
+
+function getMillisInDaysHoursMinutes(millis) {
+ if (!millis)
+ return "";
+ // millisInWorkingDay is set on partHeaderFooter
+ var sgn=millis>=0?1:-1;
+ millis=Math.abs(millis);
+ var days = Math.floor(millis / millisInWorkingDay);
+ var hour = Math.floor((millis % millisInWorkingDay) / 3600000);
+ var min = Math.floor((millis-days*millisInWorkingDay-hour*3600000) / 60000);
+ return (sgn>=0?"":"-")+(days > 0 ? days + " " : "") + pad(hour,1,"0") + ":" + pad(min,2,"0");
+}
+
+function millisFromHourMinute(stringHourMinutes) { //All this format are valid: "12:58" "13.75" "63635676000" (this is already in milliseconds)
+ var result = 0;
+ stringHourMinutes.replace(",",".");
+ var semiColSeparator = stringHourMinutes.indexOf(":");
+ var dotSeparator = stringHourMinutes.indexOf(".");
+
+ if (semiColSeparator < 0 && dotSeparator < 0 && stringHourMinutes.length > 5) {
+ return parseInt(stringHourMinutes, 10); //already in millis
+ } else {
+
+ if (dotSeparator > -1) {
+ var d = parseFloat(stringHourMinutes);
+ result = d * 3600000;
+ } else {
+ var hour = 0;
+ var minute = 0;
+ if (semiColSeparator == -1)
+ hour = parseInt(stringHourMinutes, 10);
+ else {
+ hour = parseInt(stringHourMinutes.substring(0, semiColSeparator), 10);
+ minute = parseInt(stringHourMinutes.substring(semiColSeparator + 1), 10);
+ }
+ result = hour * 3600000 + minute * 60000;
+ }
+ if (typeof(result)!="number")
+ result=NaN;
+ return result;
+ }
+}
+
+
+/**
+ * @param string "3y 4d", "4D:08:10", "12M/3d", "2H4D", "3M4d,2h", "12:30", "11", "3", "1.5", "2m/3D", "12/3d", "1234"
+ * by default 2 means 2 hours 1.5 means 1:30
+ * @param considerWorkingdays if true day lenght is from global.properties CompanyCalendar.MILLIS_IN_WORKING_DAY otherwise in 24
+ * @return milliseconds. 0 if invalid string
+ */
+function millisFromString(string,considerWorkingdays) {
+ if (!string)
+ return 0;
+
+ var regex = new RegExp("(\\d+[Yy])|(\\d+[M])|(\\d+[Ww])|(\\d+[Dd])|(\\d+[Hh])|(\\d+[m])|(\\d+[Ss])|(\\d+:\\d+)|(:\\d+)|(\\d*[\\.,]\\d+)|(\\d+)","g");
+
+ var matcher = regex.exec(string);
+ var totMillis=0;
+
+ if (!matcher)
+ return NaN;
+
+ while (matcher!=null) {
+ for (var i = 1; i < matcher.length; i++) {
+ var match = matcher[i];
+ if (match) {
+ var number = 0;
+ try {
+ number = parseInt(match);
+ } catch (e) {
+ }
+ if (i == 1) { // years
+ totMillis = totMillis + number * (considerWorkingdays ? millisInWorkingDay * workingDaysPerWeek * 52 : 3600000 * 24 * 365);
+ } else if (i == 2) { // months
+ totMillis = totMillis + number * (considerWorkingdays ? millisInWorkingDay * workingDaysPerWeek * 4 : 3600000 * 24 * 30);
+ } else if (i == 3) { // weeks
+ totMillis = totMillis + number * (considerWorkingdays ? millisInWorkingDay * workingDaysPerWeek : 3600000 * 24 * 7);
+ } else if (i == 4) { // days
+ totMillis = totMillis + number * (considerWorkingdays ? millisInWorkingDay : 3600000 * 24);
+ } else if (i == 5) { // hours
+ totMillis = totMillis + number * 3600000;
+ } else if (i == 6) { // minutes
+ totMillis = totMillis + number * 60000;
+ } else if (i == 7) { // seconds
+ totMillis = totMillis + number * 1000;
+ } else if (i == 8) { // hour:minutes
+ totMillis = totMillis + millisFromHourMinute(match);
+ } else if (i == 9) { // :minutes
+ totMillis = totMillis + millisFromHourMinute(match);
+ } else if (i == 10) { // hour.minutes
+ totMillis = totMillis + millisFromHourMinute(match);
+ } else if (i == 11) { // hours
+ totMillis = totMillis + number * 3600000;
+ }
+ }
+ }
+ matcher=regex.exec(string);
+ }
+
+ return totMillis;
+}
+
+/**
+ * @param string "3y 4d", "4D:08:10", "12M/3d", "2H4D", "3M4d,2h", "12:30", "11", "3", "1.5", "2m/3D", "12/3d", "1234"
+ * by default 2 means 2 hours 1.5 means 1:30
+ * @param considerWorkingdays if true day lenght is from global.properties CompanyCalendar.MILLIS_IN_WORKING_DAY otherwise in 24
+ * @return milliseconds. 0 if invalid string
+ */
+function daysFromString(string,considerWorkingdays) {
+ if (!string)
+ return undefined;
+
+ var regex = new RegExp("(\\d+[Yy])|(\\d+[Mm])|(\\d+[Ww])|(\\d+[Dd])|(\\d*[\\.,]\\d+)|(\\d+)","g");
+
+ var matcher = regex.exec(string);
+ var totDays=0;
+
+ if (!matcher)
+ return NaN;
+
+ while (matcher != null) {
+ for (var i = 1; i < matcher.length; i++) {
+ var match = matcher[i];
+ if (match) {
+ var number = 0;
+ try {
+ number = parseInt(match);
+ } catch (e) {
+ }
+ if (i == 1) { // years
+ totDays = totDays + number * (considerWorkingdays ? workingDaysPerWeek * 52 : 365);
+ } else if (i == 2) { // months
+ totDays = totDays + number * (considerWorkingdays ? workingDaysPerWeek * 4 : 30);
+ } else if (i == 3) { // weeks
+ totDays = totDays + number * (considerWorkingdays ? workingDaysPerWeek : 7);
+ } else if (i == 4) { // days
+ totDays = totDays + number;
+ } else if (i == 5) { // days.minutes
+ totDays = totDays + number;
+ } else if (i == 6) { // days
+ totDays = totDays + number;
+ }
+ }
+ }
+ matcher=regex.exec(string);
+ }
+
+ return totDays;
+}
+
+
+
+/* Object Functions */
+
+function stopBubble(e) {
+ if ($.browser.msie && event){
+ event.cancelBubble = true;
+ event.returnValue = false;
+
+ }else if (e){
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ return false;
+}
+
+//validation functions - used by textfield and datefield
+function validateField(ev) {
+ var el = $(this);
+ var rett=true;
+ el.clearErrorAlert();
+ // check serverside only if not empty
+ var value = el.val();
+ if (value) {
+
+ var type = el.attr('entryType').toUpperCase();
+
+ if (type == "INTEGER") {
+ rett = isValidInteger(value);
+ } else if (type == "DOUBLE") {
+ rett = isValidDouble(value);
+ } else if (type == "PERCENTILE") {
+ rett = isValidDouble(value);
+ } else if (type == "URL") {
+ rett = isValidURL(value);
+ } else if (type == "EMAIL") {
+ rett = isValidEmail(value);
+ } else if (type == "DURATIONMILLIS") {
+ rett = isValidDurationMillis(value);
+ } else if (type == "DURATIONDAYS") {
+ rett = isValidDurationDays(value);
+ } else if (type == "DATE") {
+ rett = Date.isValid(value,el.attr("format"));
+ } else if (type == "TIME") {
+ rett = isValidTime(value);
+ } else if (type == "CURRENCY") {
+ rett = isValidCurrency(value);
+ }
+
+ if (!rett) {
+ el.createErrorAlert(i18n.ERROR_ON_FIELD,i18n.INVALID_DATA);
+ }
+ }
+ return rett;
+}
+
+jQuery.fn.clearErrorAlert= function(){
+ this.each(function(){
+ var el = $(this);
+ el.removeAttr("invalid").removeClass("formElementsError");
+ $("#"+el.attr("id")+"error").remove();
+ });
+ return this;
+};
+
+jQuery.fn.createErrorAlert = function(errorCode, message) {
+ this.each(function() {
+ var el = $(this);
+ el.attr("invalid", "true").addClass("formElementsError");
+ if ($("#" + el.attr("id") + "error").size() <= 0) {
+ var errMess = (errorCode?errorCode:"") + ": " + (message?message:"");
+ var err = "<img width='17' heigh='17' id=\"" + el.attr("id") + "error\" error='1'";
+ err += " onclick=\"alert($(this).attr('title'))\" border='0' align='absmiddle'>";
+ err=$(err);
+ err.attr("title",errMess).attr("src",skinImgPath+"alert.gif");
+ el.after(err);
+ }
+ });
+ return this;
+};
+
+
+//errors =[{ceName:ceErrorCode},...]
+function jsonErrorHandling(response){
+ if (!response.ok){
+ if (response.message)
+ alert("ERROR:\n"+ response.message);
+ for (var i in response.clientEntryErrors){
+ var err=response.clientEntryErrors[i];
+ $(":input[name="+err.name+"]").createErrorAlert(err.error);
+ }
+ }
+}
+
+
+
+// ---------------------------------- oldvalues management
+// update all values selected
+jQuery.fn.updateOldValue= function(){
+ this.each(function(){
+ var el = $(this);
+ el.data("_oldvalue",el.val());
+ });
+ return this;
+};
+
+// return true if at least one element has changed
+jQuery.fn.isValueChanged=function (){
+ var ret=false;
+ this.each(function(){
+ var el = $(this);
+ if (el.val()+"" != el.data("_oldvalue") + ""){
+ //console.debug("io sono diverso "+el.attr("id")+ " :"+el.val()+" != "+el.data("_oldvalue"));
+ ret=true;
+ return false;
+ }
+ });
+ return ret;
+};
+
+jQuery.fn.getOldValue=function(){
+ return $(this).data("_oldvalue");
+};
+
+
+
+
+$.fn.unselectable=function(){
+ this.each(function(){
+ $(this).addClass("unselectable").attr("unselectable","on");
+ });
+ return $(this);
+};
+
+$.fn.clearUnselectable=function(){
+ this.each(function(){
+ $(this).removeClass("unselectable").removeAttr("unselectable");
+ });
+ return $(this);
+};
+
+
+// ---------------------------------- PROFILING ------------------------------------------
+var __profiler = {};
+/**
+ * usage: instantiate a new Profiler("a name") at the beginning of the code you want to profile var p= new Profiler("testLoop")
+ * call p.stop() at the end of the code you want test.
+ * call Profiler.displayAll() or p.display() to see how many times the code has been executed and millisecond spent.
+ * call Profiler.resetAll() or p.reset() to restart profiler.
+ * @param name
+ */
+function Profiler(name) {
+ this.startTime = new Date().getTime();
+ this.name = name;
+
+ this.stop = function() {
+ if (!__profiler[this.name])
+ __profiler[this.name] = {millis:0,count:0};
+ __profiler[this.name].millis += new Date().getTime() - this.startTime;
+ __profiler[this.name].count++;
+ };
+ this.display = function() {
+ console.debug(__profiler[this.name]);
+ };
+
+ this.reset = function() {
+ delete __profiler[this.name];
+ };
+}
+
+Profiler.reset = function() {
+ __profiler = {};
+};
+
+Profiler.displayAll = function() {
+ var ret = "";
+ var totMillis = 0;
+ for (var key in __profiler) {
+ var p = __profiler[key];
+ var extraspace=" ".substr(0,30-key.length);
+ ret += key + extraspace+ "\t millis:" + p.millis+"\t count:" + p.count + "\n";
+ totMillis += p.millis;
+ }
+ console.debug(ret);
+};
+
+
+$(document).ready(function() {
+ $(":input[oldValue]").livequery(function(){$(this).updateOldValue();});
+ $('.validated').livequery('blur', validateField);
+});
+
+function openBlackPopup(url,width,height,onCloseCallBack,iframeId){
+ if(!iframeId)
+ iframeId="bwinPopup";
+
+ if (!width)
+ width='900px';
+ if (!height)
+ height='730px';
+
+ $("#__blackpopup__").remove();
+
+ var bg=$("<div>").attr("id","__blackpopup__");
+ //bg.css({position:'fixed',top:0, left:0,width:'100%',height:'100%', backgroundImage:"url('"+contextPath+"/applications/teamwork/images/black_70.png')",textAlign:'center'});
+ bg.css({position:'fixed',top:0, left:0,width:'100%',height:'100%',textAlign:'center'});
+
+ //add black only if not already in blackpupup
+ if(window.name!=iframeId)
+ bg.css({backgroundImage:"url('"+contextPath+"/applications/teamwork/images/black_70.png')"});
+
+ bg.append("<iframe id='"+iframeId+"' name='"+iframeId+"' frameborder='0'></iframe>");
+ bg.bringToFront();
+
+
+ //close call callback
+ bg.bind("close",function(){
+ bg.slideUp(300,function(){
+ bg.remove();
+ if (typeof(onCloseCallBack)=="function")
+ onCloseCallBack();
+ });
+ });
+
+ //destroy do not call callback
+ bg.bind("destroy",function(){
+ bg.remove();
+ });
+
+ bg.find("iframe:first").attr("src",url).css({width:width, height:height,top:100,border:'8px solid #909090', backgroundColor:'#ffffff'});
+
+ var bdiv= $("<div>").css({width:width,position:"relative",height:"5px", textAlign:"right", margin:"auto" });
+ bdiv.append("<img src=\"closeBig.png\" style='cursor:pointer;position:absolute;right:-40px;top:30px;'>");
+ bdiv.find("img:first").click( function(){
+ bg.trigger("close");
+
+ });
+
+ bg.prepend(bdiv);
+ $("body").append(bg);
+}
+
+
+//returns a jquery object where to write content
+function createBlackPage(width,height,onCloseCallBack){
+ if (!width)
+ width='900px';
+ if (!height)
+ height='730px';
+
+ $("#__blackpopup__").remove();
+
+ var bg=$("<div>").attr("id","__blackpopup__");
+ bg.css({position:'fixed',top:"0px",paddingTop:"50px", left:0,width:'100%',height:'100%', backgroundImage:"url('/applications/teamwork/images/black_70.png')"});
+ bg.append("<div id='bwinPopupd' name='bwinPopupd'></div>");
+ bg.bringToFront();
+
+ var ret=bg.find("#bwinPopupd");
+ ret.css({width:width, height:height,top:10, "-moz-box-shadow":'1px 1px 6px #333333',overflow:'auto',"-webkit-box-shadow":'1px 1px 6px #333333', border:'8px solid #777', backgroundColor:"#fff", margin:"auto" });
+
+ var bdiv= $("<div>").css({width:width,position:"relative",height:"0px", textAlign:"right", margin:"auto" });
+ var img=$("<img src='closeBig.png' style='cursor:pointer;position:absolute;right:-40px;top:5px;' title='close'>");
+ bdiv.append(img);
+ img.click( function(){
+ bg.trigger("close");
+ });
+
+ bg.prepend(bdiv);
+ $("body").append(bg);
+
+ //close call callback
+ bg.bind("close",function(){
+ bg.slideUp(300,function(){
+ bg.remove();
+ if (typeof(onCloseCallBack)=="function")
+ onCloseCallBack();
+ });
+ });
+
+ //destroy do not call callback
+ bg.bind("destroy",function(){
+ bg.remove();
+ });
+ return ret;
+}
+
+
+function getBlackPopup(){
+ var ret=$("#__blackpopup__");
+ if (typeof(top)!="undefined"){
+ ret= window.parent.$("#__blackpopup__");
+ }
+ return ret;
+}
+
+
+function closeBlackPopup(){
+ getBlackPopup().trigger("close");
+}
+
+
+
+//------------------------------------------------ TEAMWORK SPECIFIC FUNCTIONS --------------------------------------------------------
+function openIssueEditorInBlack(issueId,command,params){
+ if (!command)
+ command="ED";
+ var editUrl=contextPath+"/applications/teamwork/issue/issueEditor.jsp?CM="+command+"&OBJID="+issueId;
+ if (params)
+ editUrl=editUrl+params;
+ openBlackPopup(editUrl,1020,$(window).height()-50, function(){$("#"+issueId).effect("highlight", { color: "yellow" }, 1500);});
+}
+
+function openBoardInBlack(boardId,command,params,callback){
+ if (!command)
+ command="ED";
+ var editUrl=contextPath+"/applications/teamwork/board/boardEditor.jsp?CM="+command+"&OBJID="+boardId;
+ if (params)
+ editUrl=editUrl+params;
+ openBlackPopup(editUrl,$(window).width()-100,$(window).height()-50,callback );
+}
+
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/linkArrow.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/linkArrow.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/milestone.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/milestone.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/platform.css
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/platform.css (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/platform.css 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,346 @@
+@font-face {
+ font-family: 'TeamworkRegular';
+ src: url('teamwork-regular-webfont.eot');
+ src: url('teamwork-regular-webfont.eot?#iefix') format('embedded-opentype'),
+ url('teamwork-regular-webfont.woff') format('woff'),
+ url('teamwork-regular-webfont.ttf') format('truetype'),
+ url('teamwork-regular-webfont.otf') format('opentype'),
+ url('teamwork-regular-webfont.svg#TeamworkRegular') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+
+
+
+*{
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -o-box-sizing:border-box;
+ box-sizing: border-box;
+}
+
+ /*
+ -------------------------------------------------------
+ body styles
+ -------------------------------------------------------
+ */
+BODY, TBODY {
+ font-family: arial;
+ font-size: 14px;
+ margin: 0;
+ color: #000000;
+ text-decoration: none;
+}
+
+BODY {
+ background-color: #91B4B7;
+}
+
+a {
+ text-decoration: none;
+ font-weight: bold;
+ color: #16ABDD;
+}
+
+a:hover, a.aHover {
+ color: #0C85AD;
+ text-decoration: underline;
+}
+
+h1 {
+ font-size:32px;
+ line-height: 34px;
+ color:#91B4B7;
+ font-weight:normal;
+ margin:0 0 10px 0
+}
+
+h2 {
+ font-size:22px;
+ color:#373737;
+ font-weight:normal;
+ margin:0 0 10px 0
+}
+
+h3 {
+ text-decoration: none;
+ color: #000000;
+ font-size: 16px;
+ margin: 0;
+}
+
+h4 {
+ font-size:16px;
+ padding:5px 0;
+ color:#617777;
+ margin:0
+}
+
+#savingMessage{
+ background-color:#E3EDED;
+ display:none;
+ color:#617777;
+ font-weight:bolder;
+ position:fixed;
+ top:0;
+ left:50%;
+ width:200px;
+ text-align:center;
+ margin-left:-100px;
+ padding:5px 0;
+ z-index:1000000;
+ box-shadow:0 3px 2px rgba(0,0,0,0.4);
+ -moz-box-shadow:0 3px 2px rgba(0,0,0,0.4);
+ -webkit-box-shadow:0 3px 2px rgba(0,0,0,0.4);
+ -o-box-shadow:0 3px 2px rgba(0,0,0,0.4);
+}
+
+.waiting{
+ cursor:progress;
+}
+
+/*
+ -------------------------------------------------------
+ teamwork icon
+ -------------------------------------------------------
+ */
+
+
+.teamworkIcon {
+ font-family: 'TeamworkRegular', arial, sans-serif;
+ color:#617777;
+ font-weight:normal;
+ font-size:120%
+}
+
+.teamworkIcon.withLabel {
+ padding-right:5px;
+}
+
+
+.button:hover .teamworkIcon {
+ opacity: 0.8
+}
+
+.teamworkIcon.alert {
+ color:#B61E2D;
+}
+
+.cvcColorSquare{
+ display:inline-block;
+ text-align:left;
+ border:#fff 0px solid;
+ box-shadow:0px 0px 5px #999;
+ -moz-box-shadow:2px 2px 2px #999;
+ -webkit-box-shadow:0px 0px 5px #999;
+ -o-box-shadow:0px 0px 5px #999;
+ text-indent:10px;
+ border-radius:5px
+}
+
+.cvcColorSquare:hover{
+ opacity:0.8
+}
+
+
+
+.unselectable {
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+}
+
+
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
+
+
+ /*
+ -------------------------------------------------------
+ table styles
+ -------------------------------------------------------
+ */
+
+.table {
+ width: 100%;
+}
+
+TH, .tableHeader {
+ font-weight: normal;
+ color: #FFFFFF;
+ border: none;
+ background-color: #91B4B7;
+ padding:2px
+}
+
+TH a {
+ color: #FFFFFF;
+}
+
+
+
+ /*
+ -------------------------------------------------------
+ Buttons
+ -------------------------------------------------------
+ */
+
+.button {
+ display:inline-block;
+ font-size:110%;
+ font-family:Arial, sans-serif;
+ color:#fff;
+ cursor:pointer;
+ background-color:#373737;
+ -moz-box-shadow:2px 2px 2px #999;
+ -webkit-box-shadow:2px 2px 2px #999;
+ -o-box-shadow:2px 2px 2px #999;
+ box-shadow:2px 2px 2px #999;
+ -moz-border-radius:5px;
+ -webkit-border-radius:5px;
+ -o-border-radius:5px;
+ border-radius:5px;
+ border:none;
+ padding:7px 10px;
+ margin-bottom:10px;
+ margin-right:10px;
+ text-align: center
+}
+
+
+.button.first {
+ background-color:#FEA730;
+ font-weight: bold;
+}
+.button.first:hover {
+ background-color:#D98E2A;
+}
+
+
+
+.button[disabled] {
+ cursor: default;
+ opacity:0.4
+}
+
+
+.button:hover[disabled] {
+ background-color:#BABABA
+}
+
+.button.textual, .button.buttonImg {
+ border: none;
+ background-color: transparent;
+ color:#68979B;
+ -moz-box-shadow:0 0 0 #999;
+ -webkit-box-shadow:0 0 0 #999;
+ -o-box-shadow:0 0 0 #999;
+ box-shadow:0 0 0 #999;
+ -moz-border-radius:0;
+ -webkit-border-radius:0;
+ -o-border-radius:0;
+ border-radius:0;
+ padding:0;
+ margin:0;
+ text-align: left
+}
+
+
+
+.button.edit {
+ color:#009E94;
+ padding:0;
+ margin:0
+}
+
+.button.delete {
+ color:#B61E2D;
+ padding:0;
+ margin:0
+}
+
+.button:hover {
+ background-color: #4C4C4C;
+}
+.button.textual:hover, .button.buttonImg:hover {
+ background-color: transparent;
+}
+
+span.separator {
+ display: inline-block;
+}
+
+.button.add {
+ color:#009E94;
+}
+
+.button.add .teamworkIcon {
+ color:#009E94;
+}
+
+
+form {
+ margin: 0;
+ padding: 0;
+}
+
+select {
+ border:1px solid #91B4B7;
+ padding: 4px;
+ font-size: 16px;
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+.formElements {
+ background-color: white;
+ padding: 4px;
+ font-size: 16px;
+ border:1px solid #91B4B7;
+ -moz-border-radius:3px;
+ -webkit-border-radius:3px;
+ -o-border-radius:3px;
+ border-radius:3px;
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+.formElementsError {
+ border: 1px solid #ff0000;
+}
+
+.formElementExclamation {
+ width: 15px;
+ height: 25px;
+ mmmargin-left: -20px;
+ mmmposition: absolute;
+ background: url("alert.gif") no-repeat;
+}
+
+
+span#FLD_LOGIN_NAMEerror, span#FLD_PWDerror {
+ margin-left: -23px;
+ margin-top: 2px;
+}
+
+
+input {
+ background-color: white;
+ padding: 4px;
+ font-size: 16px;
+ border:1px solid #91B4B7;
+ -moz-border-radius:3px;
+ -webkit-border-radius:3px;
+ -o-border-radius:3px;
+ border-radius:3px;
+ font-family: Arial, Helvetica, sans-serif;
+}
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.eot
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.eot
___________________________________________________________________
Added: svn:mime-type
+ application/vnd.ms-fontobject
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.otf
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.otf
___________________________________________________________________
Added: svn:mime-type
+ application/vnd.ms-opentype
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.svg
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.svg
___________________________________________________________________
Added: svn:mime-type
+ image/svg+xml
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.ttf
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.ttf
___________________________________________________________________
Added: svn:mime-type
+ application/x-font-ttf
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.woff
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamwork-regular-webfont.woff
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamworkFont.css
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamworkFont.css (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/teamworkFont.css 2013-06-20 14:35:02 UTC (rev 344)
@@ -0,0 +1,16 @@
+
+@font-face {
+ font-family: 'TeamworkRegular';
+ src: url('teamwork-regular-webfont.eot');
+ src: url('teamwork-regular-webfont.eot?#iefix') format('embedded-opentype'),
+ url('teamwork-regular-webfont.woff') format('woff'),
+ url('teamwork-regular-webfont.ttf') format('truetype'),
+ url('teamwork-regular-webfont.otf') format('opentype'),
+ url('teamwork-regular-webfont.svg#TeamworkRegular') format('svg');
+ font-weight: normal;
+ font-style: normal;
+
+}
+
+
+
Added: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/twGanttSmall.png
===================================================================
(Binary files differ)
Property changes on: trunk/chorem-webmotion/src/main/webapp/js/jQueryGantt/twGanttSmall.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
1
0
r343 - in trunk/chorem-webmotion/src/main: java/org/chorem/webmotion/actions/project java/org/wikitty/web/jsptag resources webapp/WEB-INF/jsp webapp/js
by meynier@users.chorem.org 20 Jun '13
by meynier@users.chorem.org 20 Jun '13
20 Jun '13
Author: meynier
Date: 2013-06-20 12:37:21 +0200 (Thu, 20 Jun 2013)
New Revision: 343
Url: http://chorem.org/projects/chorem/repository/revisions/343
Log:
Quotation status update added in dashboard
Added:
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/Extensions.java
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java
trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/simpleWikiFields.jsp
Modified:
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java
trunk/chorem-webmotion/src/main/java/org/wikitty/web/jsptag/WikittyInput.java
trunk/chorem-webmotion/src/main/resources/mapping
trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp
trunk/chorem-webmotion/src/main/webapp/js/chorem.js
Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-06-17 16:12:18 UTC (rev 342)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-06-20 10:37:21 UTC (rev 343)
@@ -3,11 +3,13 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
+import java.util.TreeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.debux.webmotion.server.WebMotionController;
import org.chorem.ChoremClient;
+import org.chorem.ChoremUtil;
import org.debux.webmotion.server.call.Call;
import org.debux.webmotion.server.render.Render;
import org.chorem.entities.Quotation;
@@ -33,7 +35,7 @@
WikittyQueryResult<Quotation> quotationResult = null;
WikittyQueryResult<Task> taskResult = null;
HashMap<Quotation, List<Task>> taskMap = new HashMap<Quotation, List<Task>>();
- HashMap<Quotation, WikittyExtension> extMap = new HashMap<Quotation, WikittyExtension>();
+ //HashMap<Quotation, String> extMap = new HashMap<Quotation, String>();
//Fetch the project form the name (if it has been requested)
if(id != null) {
@@ -67,7 +69,6 @@
taskResult = client.findAllByQuery(Task.class, taskQuery);
taskMap.put(quote, taskResult.getAll());
- extMap.put(quote, getNextExtension(client, quote));
}
@@ -88,7 +89,8 @@
else {
return renderView("dashboardSingleProject.jsp",
"title", "Tableau de bord projet", "projects", projectResult.getAll(),
- "quotations", quotationResult.getAll(), "taskMap", taskMap, "extMap", extMap);
+ "quotations", quotationResult.getAll(), "taskMap", taskMap, "extensions",
+ Extensions.extensions);
}
}
@@ -97,28 +99,26 @@
}
-
- private WikittyExtension getNextExtension(ChoremClient client,Quotation object) {
+ /*
+ private String getNextExtension(ChoremClient client,Quotation object) {
Collection<String> extensions = object.getExtensionNames();
if(extensions.contains("Closed")) return null;
+ TreeMap<Integer, String> extMap = new TreeMap<Integer, String>();
- String[] exts = {"Quotation", "Draft", "Sent", "Rejected", "Accepted", "Started",
- "Delivered", "RSV", "Warranty", "Closed"};
//reverse loop
for(int i = exts.length-1; i>=0; i--) {
if(extensions.contains(exts[i])) {
WikittyExtension ret = client.restoreExtensionLastVersion(exts[i+1]);
- System.out.println("EXTENSION : " + ret);
return ret;
}
}
return null;
- }
+ }*/
}
Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/Extensions.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/Extensions.java (rev 0)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/Extensions.java 2013-06-20 10:37:21 UTC (rev 343)
@@ -0,0 +1,16 @@
+package org.chorem.webmotion.actions.project;
+
+public interface Extensions {
+ public static final String[] extensions = {
+ "Quotation",
+ "Draft",
+ "Sent",
+ "Rejected",
+ "Accepted",
+ "Started",
+ "Delivered",
+ "RSV",
+ "Warranty",
+ "Closed"
+ };
+}
Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java (rev 0)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java 2013-06-20 10:37:21 UTC (rev 343)
@@ -0,0 +1,79 @@
+package org.chorem.webmotion.actions.project;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.chorem.ChoremClient;
+import org.chorem.ChoremUtil;
+import org.chorem.webmotion.actions.GenericAction;
+import org.debux.webmotion.server.WebMotionController;
+import org.debux.webmotion.server.call.Call;
+import org.debux.webmotion.server.render.Render;
+import org.nuiton.wikitty.entities.Wikitty;
+import org.nuiton.wikitty.entities.WikittyExtension;
+import org.nuiton.wikitty.entities.WikittyImpl;
+
+public class QuotationStatusAction extends GenericAction{
+
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ static private Log log = LogFactory.getLog(QuotationStatusAction.class);
+
+ public Render upgrade(ChoremClient client, String id, String[] extension, Call call) {
+ Wikitty w = upgradeInternal(client, id, extension, call);
+ getContext().addInfoMessage("message", "Object saved");
+ return renderURL("/wikitty/view/"+w.getWikittyId());
+ }
+
+ /**
+ * Method used by save and saveJson to actually perform the save action
+ * @param client
+ * @param id
+ * @param extension
+ * @param call
+ * @return the saved wikitty
+ */
+ protected Wikitty upgradeInternal(ChoremClient client, String id, String[] extensionStr, Call call) {
+
+ log.debug("save: " + id);
+ System.out.println("EXTENSIONS §§§§ : ");
+ System.out.println(Arrays.toString(extensionStr));
+ System.out.println(ChoremUtil.asList(null, extensionStr));
+ Wikitty w = client.restore(id);
+ if (w == null) { // Jamais sensé arriver
+ w = new WikittyImpl();
+ }
+
+ //System.out.println("Nom de l'extension : " + extensions);
+ List<String> extList = ChoremUtil.asList(null, extensionStr);
+ if(extList == null)
+ return w;
+ Collection<WikittyExtension> exts = client.restoreExtensionLastVersion(extList);
+
+ System.out.println("EXTENSION : " + exts);
+ w.addExtension(exts);
+ Map<String, Object> params = call.getExtractParameters();
+ String error = setWikittyField(w, "", params);
+ client.store(w);
+
+ return w;
+ }
+
+
+ public Render getExtension(ChoremClient client, String extensionName, String id) {
+ Collection<String> c = new ArrayList<String>();
+ c.add(extensionName);
+ Wikitty wikitty = client.restore(id);
+ List<WikittyExtension> extensions = client.restoreExtensionAndDependenciesLastVesion(c);
+
+ extensions.removeAll(wikitty.getExtensions());
+
+
+ return renderView("simpleWikiFields.jsp", "extensions", extensions, "wikitty", wikitty);
+ }
+
+}
Modified: trunk/chorem-webmotion/src/main/java/org/wikitty/web/jsptag/WikittyInput.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/wikitty/web/jsptag/WikittyInput.java 2013-06-17 16:12:18 UTC (rev 342)
+++ trunk/chorem-webmotion/src/main/java/org/wikitty/web/jsptag/WikittyInput.java 2013-06-20 10:37:21 UTC (rev 343)
@@ -110,19 +110,13 @@
String fieldName = WikittyUtil.getFieldNameFromFQFieldName(fqfield);
FieldType field = null;
try {
- System.out.println("JE TENTE DE RECUPERER LE TYPE");
field = wikitty.getFieldType(fqfield);
- System.out.println("LE TYPE EXISTE");
}
catch(Exception e) {
- System.out.println("LE TYPE N'EXISTE PAS");
- System.out.println("JE CATCH L'EXCEPTION");
if(extension == null) {
- System.out.println("extension EST NULL");
throw new JspException(e);
}
else {
- System.out.println("JE RECUPERE LE TYPE DEPUIS L'EXTENSION");
field = extension.getFieldType(WikittyUtil.getFieldNameFromFQFieldName(fqfield));
emptyField = true;
}
Modified: trunk/chorem-webmotion/src/main/resources/mapping
===================================================================
--- trunk/chorem-webmotion/src/main/resources/mapping 2013-06-17 16:12:18 UTC (rev 342)
+++ trunk/chorem-webmotion/src/main/resources/mapping 2013-06-20 10:37:21 UTC (rev 343)
@@ -36,6 +36,7 @@
* /wikitty/delete/{id} action:GenericAction.delete
* /wikitty/save action:GenericAction.save
* /wikitty/saveMulti action:GenericAction.saveMulti
+* /wikitty/upgrade action:project.QuotationStatusAction.upgrade
* /wikitty/view/{id}/{extension}/{field} action:GenericAction.download wmDecoratorNo=true
* /wikitty-json/searchField?q={query} action:GenericAction.searchFieldJson
* /wikitty-json/search?q={query} action:GenericAction.searchJson
@@ -67,5 +68,6 @@
* /sales/funnel/json/{method} action:sales.SalesAction.{method}
* /sales/funnel/json/{method}/{id} action:sales.SalesAction.{method}
* /project action:project.DashboardProjectAction.requestProject
+* /project/json/{method}/{extensionName}/{id} action:project.QuotationStatusAction.{method}
* /crm/account/{id} action:crm.AccountAction.view
* /crm/quotation/edit/{id} action:crm.QuotationAction.edit
Modified: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-06-17 16:12:18 UTC (rev 342)
+++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-06-20 10:37:21 UTC (rev 343)
@@ -27,31 +27,34 @@
<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%>
<h1>${title}</h1>
-<form class="well form-inline" method="GET">
+<form class="well form-inline" method="GET" id="projectSearch">
<div class="control-group">
Project Name :
<div class="controls" style="display: inline">
<script>
- $(function() {
- $( "#project_text" ).autocompleteByExtension({
- source: "/chorem/wikitty-json/search?extension=Project",
- minLength: 2,
- select: function( event, ui ) {
- $( "#project_text" ).val( ui.item.label );
- $( "#project_hidden" ).val( ui.item.id );
+ $(function() {
+ $("#project_text")
+ .autocompleteByExtension(
+ {
+ source : "/chorem/wikitty-json/search?extension=Project",
+ minLength : 2,
+ select : function(event, ui) {
+ $("#project_text").val(
+ ui.item.label);
+ $("#project_hidden")
+ .val(ui.item.id);
+ $("#project_hidden").change()
+ return false;
+ }
+ });
+ });
+ </script>
- return false;
- }
- });
- });
- </script>
-
<input type="text" id="project_text" name="project_name"
value="${param.project_name}" placeholder="project name" /> <input
- type="hidden" id="project_hidden" name="project_id" value="" /> <input
- type="submit" class="btn" />
+ type="hidden" id="project_hidden" name="project_id" value="" />
</div>
</div>
@@ -81,8 +84,8 @@
<th>Amount</th>
</tr>
</thead>
- </thead>
+
<tbody>
<tr>
<td><w:display wikitty="${q.wikitty}"
@@ -99,7 +102,6 @@
value="${q.amount / q.estimatedDays}" /></td>
<td class="currency"><w:display wikitty="${q.wikitty}"
fqfield="Quotation.amount" label="" /></td>
- </td>
</tr>
</tbody>
@@ -130,29 +132,54 @@
</c:forEach>
+ <p>
+ <select class="extBox" name="extList" wikittyId="${q.wikittyId}">
+ <option>Transformer en...</option>
+ <c:forEach items="${extensions}" var="ext">
- <c:forEach items="${extMap}" var="entry">
- <c:if test="${entry.key.equals(q)}">
- <c:if test="${entry.value != null}">
- ${entry.value.fieldNames}
- <c:forEach items="${entry.value.fieldNames}" var="field">
+ <c:set var="contains" value="false" />
+ <c:forEach var="item" items="${q.extensionNames}">
+ <c:if test="${item eq ext}">
+ <c:set var="contains" value="true" />
+ </c:if>
+ </c:forEach>
+
+ <c:if test="${contains == false}">
+ <option>${ext}</option>
+ </c:if>
+
+ </c:forEach>
+ </select>
+ </p>
+ <div id="upgradeFields-${q.wikittyId}">
+
+ </div>
+
+ <!--
+
+ <form class="form-horizontal" method="post"
+ accept-charset="ISO-8859-15"
+ action="<c:url value="/wikitty/upgrade"/>"
+ enctype="multipart/form-data">
+ <input type="hidden" name="id" value="${q.wikittyId}">
+ <c:if test="${extMap[q] != null}">
+ <fieldset>
+ <input type="hidden" name="extension" value="${extMap[q].name}">
+ <c:forEach items="${extMap[q].fieldNames}" var="field">
${field}
<div class="control-group">
<label class="control-label">${fieldName}</label>
<div class="controls">
<w:input wikitty="${q.wikitty}"
- fqfield="${entry.value.name}.${field}" extension="${entry.value}" />
+ fqfield="${extMap[q].name}.${field}" extension="${extMap[q]}" />
</div>
</div>
</c:forEach>
- <input type="button" value="Tranformer en ${entry.value.name}" />
-
- </c:if>
+ <input type="submit" value="Tranformer en ${extMap[q].name}" />
+ </fieldset>
</c:if>
-
-
-
- </c:forEach>
+ </form>
+ -->
</c:forEach>
</c:when>
Added: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/simpleWikiFields.jsp
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/simpleWikiFields.jsp (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/simpleWikiFields.jsp 2013-06-20 10:37:21 UTC (rev 343)
@@ -0,0 +1,49 @@
+<%--
+ #%L
+ Chorem webmotion
+ $Id:$
+ $HeadURL:$
+ %%
+ Copyright (C) 2011 - 2012 CodeLutin
+ %%
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ #L%
+ --%>
+<%@page contentType="text/html" pageEncoding="UTF-8"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f"%>
+<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%>
+
+<form class="form-horizontal" method="post" accept-charset="ISO-8859-15"
+ action="<c:url value="/wikitty/upgrade"/>"
+ enctype="multipart/form-data">
+ <input type="hidden" name="id" value="${wikitty.id}">
+ <c:forEach items="${extensions}" var="ext">
+ <legend>${ext.name}</legend>
+ <input type="hidden" name="extension" value="${ext.name}">
+ <c:forEach items="${ext.fieldNames}" var="field">
+ <div class="control-group">
+ <label class="control-label">${field}</label>
+ <div class="controls">
+ <w:input wikitty="${wikitty}" fqfield="${ext.name}.${field}"
+ extension="${ext}" />
+ </div>
+ </div>
+ </c:forEach>
+ </c:forEach>
+ <button class="btn btn-success" type="submit">
+ <i class="icon-ok icon-white"></i>
+ Mettre à jour
+ </button>
+</form>
\ No newline at end of file
Modified: trunk/chorem-webmotion/src/main/webapp/js/chorem.js
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/js/chorem.js 2013-06-17 16:12:18 UTC (rev 342)
+++ trunk/chorem-webmotion/src/main/webapp/js/chorem.js 2013-06-20 10:37:21 UTC (rev 343)
@@ -22,464 +22,512 @@
*/
function createUrl() {
- var result = webContext;
- for (var i = 0; i < arguments.length; i++) {
- result += arguments[i];
- }
- result = result.replace('//', '/');
- return result;
+ var result = webContext;
+ for (var i = 0; i < arguments.length; i++) {
+ result += arguments[i];
+ }
+ result = result.replace('//', '/');
+ return result;
}
$(function() {
- $('.withTooltip').tooltip({html:true});
+ $('.withTooltip').tooltip({html:true});
});
$(function() {
- $('.withPopover').popover({trigger: 'click', html:true});
+ $('.withPopover').popover({trigger: 'click', html:true});
});
$(function () {
- $.datepicker.setDefaults($.datepicker.regional['fr']);
- $.timepicker.setDefaults($.timepicker.regional['fr']);
+ $.datepicker.setDefaults($.datepicker.regional['fr']);
+ $.timepicker.setDefaults($.timepicker.regional['fr']);
});
+function initFields() {
+// tout ce qui aura la classe datepicker servira a editer une date
+ $(function() {
+ $( ".datepicker" ).datepicker({
+ showWeek: true,
+ firstDay: 1,
+ changeMonth: true,
+ changeYear: true
+ });
+// "option", "gotoCurrent", true );
+ });
+ $(function() {
+ $( ".timepicker" ).timepicker({
+ showWeek: true,
+ firstDay: 1,
+ changeMonth: true,
+ changeYear: true
+ });
+// "option", "gotoCurrent", true );
+ });
+// tout ce qui aura la classe datetimepicker servira a editer une date avec heure
+ $(function() {
+ $( ".datetimepicker" ).datetimepicker({
+ showWeek: true,
+ firstDay: 1,
+ changeMonth: true,
+ changeYear: true
+ });
+// "option", "gotoCurrent", true );
+ });
-// tout ce qui aura la classe datepicker servira a editer une date
-$(function() {
- $( ".datepicker" ).datepicker({
- showWeek: true,
- firstDay: 1,
- changeMonth: true,
- changeYear: true
- });
-// "option", "gotoCurrent", true );
-});
-$(function() {
- $( ".timepicker" ).timepicker({
- showWeek: true,
- firstDay: 1,
- changeMonth: true,
- changeYear: true
- });
-// "option", "gotoCurrent", true );
-});
-// tout ce qui aura la classe datetimepicker servira a editer une date avec heure
-$(function() {
- $( ".datetimepicker" ).datetimepicker({
- showWeek: true,
- firstDay: 1,
- changeMonth: true,
- changeYear: true
- });
-// "option", "gotoCurrent", true );
-});
-// nouveau composant pour afficher les wikitties lors de l'edition classe par extension
+}
+initFields();
+
+//nouveau composant pour afficher les wikitties lors de l'edition classe par extension
$.widget( "custom.autocompleteByExtension", $.ui.autocomplete, {
- _renderMenu: function( ul, items ) {
- var self = this,
- currentExtension = "";
- // ajout d'un element pour permettre l'effacement de l'ancienne entree
- self._renderItemData( ul, {label:"None", value:"None", name:"None"} );
- $.each( items, function( index, item ) {
- if ( item.extension != currentExtension ) {
- ul.append( "<li class='ui-autocomplete-category'>" + item.extension + "</li>" );
- currentExtension = item.extension;
- }
- self._renderItemData( ul, item );
- });
- }
+ _renderMenu: function( ul, items ) {
+ var self = this,
+ currentExtension = "";
+ // ajout d'un element pour permettre l'effacement de l'ancienne entree
+ self._renderItemData( ul, {label:"None", value:"None", name:"None"} );
+ $.each( items, function( index, item ) {
+ if ( item.extension != currentExtension ) {
+ ul.append( "<li class='ui-autocomplete-category'>" + item.extension + "</li>" );
+ currentExtension = item.extension;
+ }
+ self._renderItemData( ul, item );
+ });
+ }
});
+//ajout ble
+//clic sur les cases à cocher half-day d'une vacation (VacationRequest)
-// ajout ble
-// clic sur les cases à cocher half-day d'une vacation (VacationRequest)
-
function change12or00(dt,dtVal,tim) {
- if (tim) {
- dtVal = dtVal.substring(0,11)+"12:00";
- }
- else {
- dtVal = dtVal.substring(0,11)+"00:00";
- }
- dt.val(dtVal);
+ if (tim) {
+ dtVal = dtVal.substring(0,11)+"12:00";
+ }
+ else {
+ dtVal = dtVal.substring(0,11)+"00:00";
+ }
+ dt.val(dtVal);
}
$(document).ready(function() {
- $('.beginDateTR :checkbox').change(function(){
- var dtetim = $(this).parent().parent().children('.beginDateTD').children('input');
- var dtetimVal = dtetim.attr("value");
- change12or00(dtetim,dtetimVal,$(this).attr("checked"));
- });
+ $('.beginDateTR :checkbox').change(function(){
+ var dtetim = $(this).parent().parent().children('.beginDateTD').children('input');
+ var dtetimVal = dtetim.attr("value");
+ change12or00(dtetim,dtetimVal,$(this).attr("checked"));
+ });
});
$(document).ready(function() {
- $('.endDateTR :checkbox').change(function(){
- var dtetim = $(this).parent().parent().children('.endDateTD').children('input');
- var dtetimVal = dtetim.attr("value");
- change12or00(dtetim,dtetimVal,$(this).attr("checked"));
- });
+ $('.endDateTR :checkbox').change(function(){
+ var dtetim = $(this).parent().parent().children('.endDateTD').children('input');
+ var dtetimVal = dtetim.attr("value");
+ change12or00(dtetim,dtetimVal,$(this).attr("checked"));
+ });
});
-// ajout d'une vacation dans editVacationRequest
+//ajout d'une vacation dans editVacationRequest
$(document).ready(function() {
- $('#btn-vacation-add').click(function(){
+ $('#btn-vacation-add').click(function(){
- jQuery.ajax({
- type: 'GET',
- url: createUrl('/hr/vacationDiv/new'),
- data:'',
- sucess: function(data, textStatus, jqXHR){
-
- },
- error: function(jqXHR, textStatus, errorThrown) {
-
- }
- })
- })
-
+ jQuery.ajax({
+ type: 'GET',
+ url: createUrl('/hr/vacationDiv/new'),
+ data:'',
+ sucess: function(data, textStatus, jqXHR){
+
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+
+ }
+ })
+ })
+
});
$(document).ready(function($) {
- // ********************************************************************
- // * ACCOUNT EDITING *
- // ********************************************************************
+ // ********************************************************************
+ // * ACCOUNT EDITING *
+ // ********************************************************************
- //Edition inline des ContactDetails
- $(".contactDetail-edit-inline").click(function() {
- var button = $(this);
- var span = button.parent().children("span[wikittyId].value");
- var value = span.text();
- var id = span.attr('wikittyId');
- var input = $("<input type='text' value='"+value+"'></input>");
- input.keyup(function (e) {
- if (e.keyCode == 13) {
- value = input.val();
- $.get(createUrl("/wikitty-json/save?id=", id, "&extension=ContactDetails&ContactDetails.value=", value),
- function(){
- //success
- span.text(value);
- input.replaceWith(span);
- //ajoute un logo ok
- var okIcon = $("<i class='icon-ok'></i>");
- button.after(okIcon);
- //timeout 3s
- setTimeout(function() { okIcon.remove(); }, 3000);
- }).fail(function(){
- //fail
- input.replaceWith(span);
- //ajoute un logo erreur
- var errorIcon = $("<i class='icon-exclamation-sign'></i>");
- button.after(errorIcon);
- //timeout 3s
- setTimeout(function() { errorIcon.remove(); }, 3000);
+ //Edition inline des ContactDetails
+ $(".contactDetail-edit-inline").click(function() {
+ var button = $(this);
+ var span = button.parent().children("span[wikittyId].value");
+ var value = span.text();
+ var id = span.attr('wikittyId');
+ var input = $("<input type='text' value='"+value+"'></input>");
+ input.keyup(function (e) {
+ if (e.keyCode == 13) {
+ value = input.val();
+ $.get(createUrl("/wikitty-json/save?id=", id, "&extension=ContactDetails&ContactDetails.value=", value),
+ function(){
+ //success
+ span.text(value);
+ input.replaceWith(span);
+ //ajoute un logo ok
+ var okIcon = $("<i class='icon-ok'></i>");
+ button.after(okIcon);
+ //timeout 3s
+ setTimeout(function() { okIcon.remove(); }, 3000);
+ }).fail(function(){
+ //fail
+ input.replaceWith(span);
+ //ajoute un logo erreur
+ var errorIcon = $("<i class='icon-exclamation-sign'></i>");
+ button.after(errorIcon);
+ //timeout 3s
+ setTimeout(function() { errorIcon.remove(); }, 3000);
- });
+ });
- } else if (e.keyCode == 27) {
- input.replaceWith(span);
- }
- });
- input.blur(function() {
- input.replaceWith(span);
- });
+ } else if (e.keyCode == 27) {
+ input.replaceWith(span);
+ }
+ });
+ input.blur(function() {
+ input.replaceWith(span);
+ });
- span.replaceWith(input);
- input.focus();
- });
+ span.replaceWith(input);
+ input.focus();
+ });
- //Ajout d'une note sur un compte client
- $(".add-note").submit(function() {
- var form = $(this).get(0);
- var title = $("#note-title").val();
- var content = $("#note-content").val();
- var id = $(".elementId").html();
- var date = $.datepicker.formatDate('dd/mm/yy', new Date());
+ //Ajout d'une note sur un compte client
+ $(".add-note").submit(function() {
+ var form = $(this).get(0);
+ var title = $("#note-title").val();
+ var content = $("#note-content").val();
+ var id = $(".elementId").html();
+ var date = $.datepicker.formatDate('dd/mm/yy', new Date());
- $.get(createUrl("/wikitty-json/save?extension=Note&Note.target=", id,
- "&Note.title=", title,
- "&Note.content=", content,
- "&Note.date=", date),function(data){
- //success
- var note;
- $.each(data, function(key, val) {
- if (key=="fieldValue"){
- var savedDate = new Date(val["Note.date"]);
+ $.get(createUrl("/wikitty-json/save?extension=Note&Note.target=", id,
+ "&Note.title=", title,
+ "&Note.content=", content,
+ "&Note.date=", date),function(data){
+ //success
+ var note;
+ $.each(data, function(key, val) {
+ if (key=="fieldValue"){
+ var savedDate = new Date(val["Note.date"]);
- note = $('<li><h6 class="pull-left"><i class="icon-comment"></i> ' +
- val["Note.title"] +'</h6><small class="pull-right note-date">' +
- $.datepicker.formatDate('dd-mm-yy', savedDate) +
- '</small><div style="clear:both;"/><small>' +
- val["Note.content"] + '</small></li>');
- }
- });
- var notes = $(".notes");
- notes.prepend(note);
- form.reset();
- }).fail(function(){
- //fail
- //TODO JC20130210 retour utilisateur
+ note = $('<li><h6 class="pull-left"><i class="icon-comment"></i> ' +
+ val["Note.title"] +'</h6><small class="pull-right note-date">' +
+ $.datepicker.formatDate('dd-mm-yy', savedDate) +
+ '</small><div style="clear:both;"/><small>' +
+ val["Note.content"] + '</small></li>');
+ }
+ });
+ var notes = $(".notes");
+ notes.prepend(note);
+ form.reset();
+ }).fail(function(){
+ //fail
+ //TODO JC20130210 retour utilisateur
- });
+ });
- return false;
- });
+ return false;
+ });
- // ********************************************************************
- // * SALES FUNNEL *
- // ********************************************************************
+ // ********************************************************************
+ // * SALES FUNNEL *
+ // ********************************************************************
- function leadToDraft() {
- var id = $(this).attr('wikittyId');
- var oldQuotation = $(this).parent();
- $.get(createUrl("/sales/funnel/json/answer/", id),
- function(data){
- //success
- var wikittyId = data.meta.id;
- var wikitty = data.data;
+ function leadToDraft() {
+ var id = $(this).attr('wikittyId');
+ var oldQuotation = $(this).parent();
+ $.get(createUrl("/sales/funnel/json/answer/", id),
+ function(data){
+ //success
+ var wikittyId = data.meta.id;
+ var wikitty = data.data;
- var li = $("<li></li>").addClass("salesFunnelItem draft");
+ var li = $("<li></li>").addClass("salesFunnelItem draft");
- //leftDiv
- var leftDiv = $("<div></div>").addClass("pull-left");
- var aIconEdit = $("<a></a>")
- .attr("href", createUrl("/wikitty/edit/", wikittyId));
- var iconEdit = $("<i></i>").addClass("icon-edit");
- aIconEdit.append(iconEdit);
- leftDiv.append(aIconEdit);
- var smallAccount = $("<small></small>");
- if (wikitty["Quotation.customer"]!=null){
- var customer = data.preloaded[wikitty["Quotation.customer"]];
- var firstName = customer.preloaded[customer.data["Employee.person"]].data["Person.firstName"];
- var lastName = customer.preloaded[customer.data["Employee.person"]].data["Person.lastName"];
- var company = customer.preloaded[customer.data["Employee.company"]].data["Company.name"];
- }
- var aAccount = $("<a></a>")
- .text(firstName + " " + lastName + " (" + company + ")")
- .attr("href",createUrl("/wikitty/Employee/view/", wikitty["Quotation.customer"]));
- smallAccount.append(aAccount);
- leftDiv.append(smallAccount);
- var leftP = $("<p> - </p>");
- var itemTitleSpan = $('<span></span>').addClass('salesFunnelItemTitle');
+ //leftDiv
+ var leftDiv = $("<div></div>").addClass("pull-left");
+ var aIconEdit = $("<a></a>")
+ .attr("href", createUrl("/wikitty/edit/", wikittyId));
+ var iconEdit = $("<i></i>").addClass("icon-edit");
+ aIconEdit.append(iconEdit);
+ leftDiv.append(aIconEdit);
+ var smallAccount = $("<small></small>");
+ if (wikitty["Quotation.customer"]!=null){
+ var customer = data.preloaded[wikitty["Quotation.customer"]];
+ var firstName = customer.preloaded[customer.data["Employee.person"]].data["Person.firstName"];
+ var lastName = customer.preloaded[customer.data["Employee.person"]].data["Person.lastName"];
+ var company = customer.preloaded[customer.data["Employee.company"]].data["Company.name"];
+ }
+ var aAccount = $("<a></a>")
+ .text(firstName + " " + lastName + " (" + company + ")")
+ .attr("href",createUrl("/wikitty/Employee/view/", wikitty["Quotation.customer"]));
+ smallAccount.append(aAccount);
+ leftDiv.append(smallAccount);
+ var leftP = $("<p> - </p>");
+ var itemTitleSpan = $('<span></span>').addClass('salesFunnelItemTitle');
- if (wikitty["Quotation.project"]!=null) {
- var aProject = $("<a/>")
- .addClass("nameLink")
- .attr("href" , createUrl("/wikitty/Project/view/", wikitty["Quotation.project"]))
- .text(data.preloaded[wikitty["Quotation.project"]].data["Project.name"]);
- }
- itemTitleSpan.append(aProject);
- var descriptionSmall = $('<small/>').text(wikitty["Quotation.description"]);
- leftP.append(descriptionSmall);
- leftP.prepend(itemTitleSpan);
- leftDiv.append(leftP);
+ if (wikitty["Quotation.project"]!=null) {
+ var aProject = $("<a/>")
+ .addClass("nameLink")
+ .attr("href" , createUrl("/wikitty/Project/view/", wikitty["Quotation.project"]))
+ .text(data.preloaded[wikitty["Quotation.project"]].data["Project.name"]);
+ }
+ itemTitleSpan.append(aProject);
+ var descriptionSmall = $('<small/>').text(wikitty["Quotation.description"]);
+ leftP.append(descriptionSmall);
+ leftP.prepend(itemTitleSpan);
+ leftDiv.append(leftP);
- //button
- var aSend = $('<a/>')
- .attr('wikittyId', wikittyId)
- .addClass("btn btn-success pull-right salesFunnelItemButton draft")
- .text("Envoyer")
- .click(draftToSent);
+ //button
+ var aSend = $('<a/>')
+ .attr('wikittyId', wikittyId)
+ .addClass("btn btn-success pull-right salesFunnelItemButton draft")
+ .text("Envoyer")
+ .click(draftToSent);
- //rightDiv
- var rightDiv = $("<div>").addClass("pull-right");
- var rightP = $("<p>").addClass("salesFunnelItemTitle").text(wikitty["Quotation.amount"] +" €");
- if (wikitty["Quotation.category"] != null) {
- var smallInfo = $("<small>")
- .text(data.preloaded[wikitty["Quotation.category"]].data["WikittyTreeNode.name"]
- + ' - ' + wikitty["Quotation.estimatedDays"] + 'j - ' +
- wikitty["Quotation.conversionHope"] + "%");
- }
- rightDiv.append(rightP);
- rightDiv.append(smallInfo);
+ //rightDiv
+ var rightDiv = $("<div>").addClass("pull-right");
+ var rightP = $("<p>").addClass("salesFunnelItemTitle").text(wikitty["Quotation.amount"] +" €");
+ if (wikitty["Quotation.category"] != null) {
+ var smallInfo = $("<small>")
+ .text(data.preloaded[wikitty["Quotation.category"]].data["WikittyTreeNode.name"]
+ + ' - ' + wikitty["Quotation.estimatedDays"] + 'j - ' +
+ wikitty["Quotation.conversionHope"] + "%");
+ }
+ rightDiv.append(rightP);
+ rightDiv.append(smallInfo);
- //clear:both
- var clearBoth=$("<div style='clear:both;'/>")
+ //clear:both
+ var clearBoth=$("<div style='clear:both;'/>")
- li.append(leftDiv);
- li.append(aSend);
- li.append(rightDiv);
- li.append(clearBoth);
+ li.append(leftDiv);
+ li.append(aSend);
+ li.append(rightDiv);
+ li.append(clearBoth);
- var drafts = $(".drafts");
- drafts.append(li);
- oldQuotation.slideUp();
+ var drafts = $(".drafts");
+ drafts.append(li);
+ oldQuotation.slideUp();
- //update draftAmount and draftAmountHope
- var draftAmount = parseInt($("#draftAmount").text()) + wikitty["Quotation.amount"];
- var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
- var draftAmountHope = parseInt($("#draftAmountHope").text()) + amountHope;
- $("#draftAmount").text(draftAmount);
- $("#draftAmountHope").text(draftAmountHope);
+ //update draftAmount and draftAmountHope
+ var draftAmount = parseInt($("#draftAmount").text()) + wikitty["Quotation.amount"];
+ var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
+ var draftAmountHope = parseInt($("#draftAmountHope").text()) + amountHope;
+ $("#draftAmount").text(draftAmount);
+ $("#draftAmountHope").text(draftAmountHope);
- //update leadAmount and leadAmountHope
- var leadAmount = parseInt($("#leadAmount").text()) - wikitty["Quotation.amount"];
- var leadAmountHope = parseInt($("#leadAmountHope").text()) - amountHope;
- $("#leadAmount").text(leadAmount);
- $("#leadAmountHope").text(leadAmountHope);
+ //update leadAmount and leadAmountHope
+ var leadAmount = parseInt($("#leadAmount").text()) - wikitty["Quotation.amount"];
+ var leadAmountHope = parseInt($("#leadAmountHope").text()) - amountHope;
+ $("#leadAmount").text(leadAmount);
+ $("#leadAmountHope").text(leadAmountHope);
- }).fail(function(){
- //fail
- //TODO JC20130212 retour utilisateur
- });
- }
+ }).fail(function(){
+ //fail
+ //TODO JC20130212 retour utilisateur
+ });
+ }
- function draftToSent() {
- var id = $(this).attr('wikittyId');
- var oldQuotation = $(this).parent();
- $.get(createUrl("/sales/funnel/json/send/", id),
- function(data){
- //success
+ function draftToSent() {
+ var id = $(this).attr('wikittyId');
+ var oldQuotation = $(this).parent();
+ $.get(createUrl("/sales/funnel/json/send/", id),
+ function(data){
+ //success
- var wikittyId = data.meta.id;
- var wikitty = data.data;
+ var wikittyId = data.meta.id;
+ var wikitty = data.data;
- var li = $("<li></li>").addClass("salesFunnelItem draft");
+ var li = $("<li></li>").addClass("salesFunnelItem draft");
- //leftDiv
- var leftDiv = $("<div></div>").addClass("pull-left");
- var aIconEdit = $("<a></a>")
- .attr("href",createUrl("/wikitty/edit/", wikittyId));
- var iconEdit = $("<i></i>").addClass("icon-edit");
- aIconEdit.append(iconEdit);
- leftDiv.append(aIconEdit);
- var smallAccount = $("<small></small>");
- if (wikitty["Quotation.customer"]!=null){
- var customer = data.preloaded[wikitty["Quotation.customer"]];
- var firstName = customer.preloaded[customer.data["Employee.person"]].data["Person.firstName"];
- var lastName = customer.preloaded[customer.data["Employee.person"]].data["Person.lastName"];
- var company = customer.preloaded[customer.data["Employee.company"]].data["Company.name"];
- }
- var aAccount = $("<a></a>")
- .text(firstName + " " + lastName + " (" + company + ")")
- .attr("href", createUrl("/wikitty/Employee/view/", wikitty["Quotation.customer"]));
- smallAccount.append(aAccount);
- leftDiv.append(smallAccount);
- var leftP = $("<p> - </p>");
- var itemTitleSpan = $('<span></span>').addClass('salesFunnelItemTitle');
+ //leftDiv
+ var leftDiv = $("<div></div>").addClass("pull-left");
+ var aIconEdit = $("<a></a>")
+ .attr("href",createUrl("/wikitty/edit/", wikittyId));
+ var iconEdit = $("<i></i>").addClass("icon-edit");
+ aIconEdit.append(iconEdit);
+ leftDiv.append(aIconEdit);
+ var smallAccount = $("<small></small>");
+ if (wikitty["Quotation.customer"]!=null){
+ var customer = data.preloaded[wikitty["Quotation.customer"]];
+ var firstName = customer.preloaded[customer.data["Employee.person"]].data["Person.firstName"];
+ var lastName = customer.preloaded[customer.data["Employee.person"]].data["Person.lastName"];
+ var company = customer.preloaded[customer.data["Employee.company"]].data["Company.name"];
+ }
+ var aAccount = $("<a></a>")
+ .text(firstName + " " + lastName + " (" + company + ")")
+ .attr("href", createUrl("/wikitty/Employee/view/", wikitty["Quotation.customer"]));
+ smallAccount.append(aAccount);
+ leftDiv.append(smallAccount);
+ var leftP = $("<p> - </p>");
+ var itemTitleSpan = $('<span></span>').addClass('salesFunnelItemTitle');
- if (wikitty["Quotation.project"]!=null) {
- var aProject = $("<a/>")
- .addClass("nameLink")
- .attr("href" , createUrl("/wikitty/Project/view/", wikitty["Quotation.project"]))
- .text(data.preloaded[wikitty["Quotation.project"]].data["Project.name"]);
- }
- itemTitleSpan.append(aProject);
- var descriptionSmall = $('<small/>').text(wikitty["Quotation.description"]);
- leftP.append(descriptionSmall);
- leftP.prepend(itemTitleSpan);
- leftDiv.append(leftP);
+ if (wikitty["Quotation.project"]!=null) {
+ var aProject = $("<a/>")
+ .addClass("nameLink")
+ .attr("href" , createUrl("/wikitty/Project/view/", wikitty["Quotation.project"]))
+ .text(data.preloaded[wikitty["Quotation.project"]].data["Project.name"]);
+ }
+ itemTitleSpan.append(aProject);
+ var descriptionSmall = $('<small/>').text(wikitty["Quotation.description"]);
+ leftP.append(descriptionSmall);
+ leftP.prepend(itemTitleSpan);
+ leftDiv.append(leftP);
- //button
- var aAccepted = $('<a/>')
- .attr('wikittyId', wikittyId)
- .addClass("btn btn-success pull-right salesFunnelItemButton sent toAccepted")
- .text("Accepté")
- .click(sentToAccepted);
- var aRejected = $('<a/>')
- .attr('wikittyId', wikittyId)
- .addClass("btn btn-danger pull-right salesFunnelItemButton sent toRejected")
- .text("Rejeté")
- .click(sentToRejected);
+ //button
+ var aAccepted = $('<a/>')
+ .attr('wikittyId', wikittyId)
+ .addClass("btn btn-success pull-right salesFunnelItemButton sent toAccepted")
+ .text("Accepté")
+ .click(sentToAccepted);
+ var aRejected = $('<a/>')
+ .attr('wikittyId', wikittyId)
+ .addClass("btn btn-danger pull-right salesFunnelItemButton sent toRejected")
+ .text("Rejeté")
+ .click(sentToRejected);
- //rightDiv
- var rightDiv = $("<div>").addClass("pull-right");
- var rightP = $("<p>").addClass("salesFunnelItemTitle").text(wikitty["Quotation.amount"] +" €");
- if (wikitty["Quotation.category"] != null) {
- var smallInfo = $("<small>")
- .text(data.preloaded[wikitty["Quotation.category"]].data["WikittyTreeNode.name"]
- + ' - ' + wikitty["Quotation.estimatedDays"] + 'j - ' +
- wikitty["Quotation.conversionHope"] + "%");
- }
- rightDiv.append(rightP);
- rightDiv.append(smallInfo);
+ //rightDiv
+ var rightDiv = $("<div>").addClass("pull-right");
+ var rightP = $("<p>").addClass("salesFunnelItemTitle").text(wikitty["Quotation.amount"] +" €");
+ if (wikitty["Quotation.category"] != null) {
+ var smallInfo = $("<small>")
+ .text(data.preloaded[wikitty["Quotation.category"]].data["WikittyTreeNode.name"]
+ + ' - ' + wikitty["Quotation.estimatedDays"] + 'j - ' +
+ wikitty["Quotation.conversionHope"] + "%");
+ }
+ rightDiv.append(rightP);
+ rightDiv.append(smallInfo);
- //clear:both
- var clearBoth=$("<div style='clear:both;'/>")
+ //clear:both
+ var clearBoth=$("<div style='clear:both;'/>")
- li.append(leftDiv);
- li.append(aAccepted);
- li.append(aRejected);
- li.append(rightDiv);
- li.append(clearBoth);
+ li.append(leftDiv);
+ li.append(aAccepted);
+ li.append(aRejected);
+ li.append(rightDiv);
+ li.append(clearBoth);
- var sents = $(".sents");
- sents.append(li);
- oldQuotation.slideUp();
+ var sents = $(".sents");
+ sents.append(li);
+ oldQuotation.slideUp();
- //update draftAmount and draftAmountHope
- var draftAmount = parseInt($("#draftAmount").text()) - wikitty["Quotation.amount"];
- var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
- var draftAmountHope = parseInt($("#draftAmountHope").text()) - amountHope;
- $("#draftAmount").text(draftAmount);
- $("#draftAmountHope").text(draftAmountHope);
+ //update draftAmount and draftAmountHope
+ var draftAmount = parseInt($("#draftAmount").text()) - wikitty["Quotation.amount"];
+ var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
+ var draftAmountHope = parseInt($("#draftAmountHope").text()) - amountHope;
+ $("#draftAmount").text(draftAmount);
+ $("#draftAmountHope").text(draftAmountHope);
- //update sentAmount and sentAmountHope
- var sentAmount = parseInt($("#sentAmount").text()) + wikitty["Quotation.amount"];
- var sentAmountHope = parseInt($("#sentAmountHope").text()) + amountHope;
- $("#sentAmount").text(sentAmount);
- $("#sentAmountHope").text(sentAmountHope);
+ //update sentAmount and sentAmountHope
+ var sentAmount = parseInt($("#sentAmount").text()) + wikitty["Quotation.amount"];
+ var sentAmountHope = parseInt($("#sentAmountHope").text()) + amountHope;
+ $("#sentAmount").text(sentAmount);
+ $("#sentAmountHope").text(sentAmountHope);
- }).fail(function(){
- //fail
- //TODO JC20130212 retour utilisateur
- });
- }
+ }).fail(function(){
+ //fail
+ //TODO JC20130212 retour utilisateur
+ });
+ }
- function sentToRejected(){
- var id = $(this).attr('wikittyId');
- var oldQuotation = $(this).parent();
- $.get(createUrl("/sales/funnel/json/reject/", id),
- function(data){
- //success
- oldQuotation.slideUp();
+ function sentToRejected(){
+ var id = $(this).attr('wikittyId');
+ var oldQuotation = $(this).parent();
+ $.get(createUrl("/sales/funnel/json/reject/", id),
+ function(data){
+ //success
+ oldQuotation.slideUp();
- var wikitty = data.data;
+ var wikitty = data.data;
- //update sentAmount and sentAmountHope
- var sentAmount = parseInt($("#sentAmount").text()) - wikitty["Quotation.amount"];
- var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
- var sentAmountHope = parseInt($("#sentAmountHope").text()) - amountHope;
- $("#sentAmount").text(sentAmount);
- $("#sentAmountHope").text(sentAmountHope);
- }).fail(function(){
- //fail
- //TODO JC20130212 retour utilisateur
- });
- }
+ //update sentAmount and sentAmountHope
+ var sentAmount = parseInt($("#sentAmount").text()) - wikitty["Quotation.amount"];
+ var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
+ var sentAmountHope = parseInt($("#sentAmountHope").text()) - amountHope;
+ $("#sentAmount").text(sentAmount);
+ $("#sentAmountHope").text(sentAmountHope);
+ }).fail(function(){
+ //fail
+ //TODO JC20130212 retour utilisateur
+ });
+ }
- function sentToAccepted(){
- var id = $(this).attr('wikittyId');
- var oldQuotation = $(this).parent();
- $.get(createUrl("/sales/funnel/json/accept/", id),
- function(data){
- //success
- oldQuotation.slideUp();
+ function sentToAccepted(){
+ var id = $(this).attr('wikittyId');
+ var oldQuotation = $(this).parent();
+ $.get(createUrl("/sales/funnel/json/accept/", id),
+ function(data){
+ //success
+ oldQuotation.slideUp();
- var wikitty = data.data;
+ var wikitty = data.data;
- //update sentAmount and sentAmountHope
- var sentAmount = parseInt($("#sentAmount").text()) - wikitty["Quotation.amount"];
- var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
- var sentAmountHope = parseInt($("#sentAmountHope").text()) - amountHope;
- $("#sentAmount").text(sentAmount);
- $("#sentAmountHope").text(sentAmountHope);
- }).fail(function(){
- //fail
- //TODO JC20130212 retour utilisateur
- });
- }
+ //update sentAmount and sentAmountHope
+ var sentAmount = parseInt($("#sentAmount").text()) - wikitty["Quotation.amount"];
+ var amountHope = wikitty["Quotation.amount"]*wikitty["Quotation.conversionHope"]/100;
+ var sentAmountHope = parseInt($("#sentAmountHope").text()) - amountHope;
+ $("#sentAmount").text(sentAmount);
+ $("#sentAmountHope").text(sentAmountHope);
+ }).fail(function(){
+ //fail
+ //TODO JC20130212 retour utilisateur
+ });
+ }
- //Passage d'un lead -> draft
- $("a.lead").click(leadToDraft);
+ //Passage d'un lead -> draft
+ $("a.lead").click(leadToDraft);
- //Passage d'un draft -> sent
- $("a.draft").click(draftToSent);
+ //Passage d'un draft -> sent
+ $("a.draft").click(draftToSent);
- //Passage d'un sent vers accepted
- $("a.toAccepted").click(sentToAccepted);
+ //Passage d'un sent vers accepted
+ $("a.toAccepted").click(sentToAccepted);
- //Passage d'un sent vers rejected
- $("a.toRejected").click(sentToRejected);
+ //Passage d'un sent vers rejected
+ $("a.toRejected").click(sentToRejected);
+
+
+ // ********************************************************************
+ // * PROJECT DASHBOARD *
+ // ********************************************************************
+
+ function upgradeQuotation() {
+
+
+ }
+
+
+
+ function displayFields() {
+ var id = $(this).attr('wikittyId');
+ $("#upgradeFields-" + id ).text("Loading fields for " + this.item(this.selectedIndex).label + "...");
+ var extensionName = this.item(this.selectedIndex).label;
+ $.get(createUrl("/project/json/getExtension/", extensionName, "/" + $(this).attr('wikittyId')),
+ function(data){
+ //success
+ var el = document.createElement( 'div' );
+ el.innerHTML = data;
+
+ var view = el.getElementsByClassName("well")[0];
+ var dateFields = view.getElementsByClassName("datepicker");
+ var d = new Date();
+ for(var i = 0; i < dateFields.length; i++) {
+ dateFields[i].value = d.getDate() + "/" + (d.getMonth() +1) + "/" + d.getFullYear();
+ //alert(dateFields[i].value);
+ }
+
+ $("#upgradeFields-" + id).html(view.innerHTML);
+ initFields();
+
+
+
+ });
+
+ }
+
+ $("a.upgrade").click(upgradeQuotation);
+ $("select.extBox").change(displayFields);
+ $("#project_hidden").change(function() {
+ $("#projectSearch").submit();
+ });
});
\ No newline at end of file
1
0
r342 - in trunk/chorem-webmotion/src/main: java/org/chorem/webmotion/actions/project java/org/wikitty/web/jsptag webapp/WEB-INF webapp/WEB-INF/jsp
by meynier@users.chorem.org 17 Jun '13
by meynier@users.chorem.org 17 Jun '13
17 Jun '13
Author: meynier
Date: 2013-06-17 18:12:18 +0200 (Mon, 17 Jun 2013)
New Revision: 342
Url: http://chorem.org/projects/chorem/repository/revisions/342
Log:
Modified WikittyInput tag to generate input from WikittyExtensions and slightly enhanced the project dashboard for the status modification form
Modified:
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java
trunk/chorem-webmotion/src/main/java/org/wikitty/web/jsptag/WikittyInput.java
trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp
trunk/chorem-webmotion/src/main/webapp/WEB-INF/wikitty.tld
Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-06-14 14:03:04 UTC (rev 341)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-06-17 16:12:18 UTC (rev 342)
@@ -1,5 +1,6 @@
package org.chorem.webmotion.actions.project;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -12,10 +13,15 @@
import org.chorem.entities.Quotation;
import org.chorem.entities.Project;
import org.chorem.entities.Task;
+import org.nuiton.wikitty.entities.WikittyExtension;
import org.nuiton.wikitty.query.WikittyQuery;
import org.nuiton.wikitty.query.WikittyQueryMaker;
import org.nuiton.wikitty.query.WikittyQueryResult;
-
+/**
+ *
+ * @author meynier
+ *
+ */
public class DashboardProjectAction extends WebMotionController {
/** to use log facility, just put in your code: log.info(\"...\"); */
@@ -27,11 +33,12 @@
WikittyQueryResult<Quotation> quotationResult = null;
WikittyQueryResult<Task> taskResult = null;
HashMap<Quotation, List<Task>> taskMap = new HashMap<Quotation, List<Task>>();
+ HashMap<Quotation, WikittyExtension> extMap = new HashMap<Quotation, WikittyExtension>();
//Fetch the project form the name (if it has been requested)
if(id != null) {
WikittyQuery projectQuery = new WikittyQueryMaker()
- .eq(Project.ELEMENT_FIELD_PROJECT_NAME, id)
+ .ideq(id)
.end();
projectResult = client.findAllByQuery(Project.class, projectQuery);
@@ -60,6 +67,7 @@
taskResult = client.findAllByQuery(Task.class, taskQuery);
taskMap.put(quote, taskResult.getAll());
+ extMap.put(quote, getNextExtension(client, quote));
}
@@ -80,11 +88,37 @@
else {
return renderView("dashboardSingleProject.jsp",
"title", "Tableau de bord projet", "projects", projectResult.getAll(),
- "quotations", quotationResult.getAll(), "taskMap", taskMap);
+ "quotations", quotationResult.getAll(), "taskMap", taskMap, "extMap", extMap);
}
}
- public Render requestProject(ChoremClient client, String projectname) {
- return projectFilter(client, projectname);
+ public Render requestProject(ChoremClient client, String project_id) {
+ return projectFilter(client, project_id);
}
+
+
+
+ private WikittyExtension getNextExtension(ChoremClient client,Quotation object) {
+ Collection<String> extensions = object.getExtensionNames();
+
+
+ if(extensions.contains("Closed")) return null;
+
+
+ String[] exts = {"Quotation", "Draft", "Sent", "Rejected", "Accepted", "Started",
+ "Delivered", "RSV", "Warranty", "Closed"};
+
+
+ //reverse loop
+ for(int i = exts.length-1; i>=0; i--) {
+ if(extensions.contains(exts[i])) {
+ WikittyExtension ret = client.restoreExtensionLastVersion(exts[i+1]);
+ System.out.println("EXTENSION : " + ret);
+ return ret;
+ }
+
+ }
+ return null;
+
+ }
}
Modified: trunk/chorem-webmotion/src/main/java/org/wikitty/web/jsptag/WikittyInput.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/wikitty/web/jsptag/WikittyInput.java 2013-06-14 14:03:04 UTC (rev 341)
+++ trunk/chorem-webmotion/src/main/java/org/wikitty/web/jsptag/WikittyInput.java 2013-06-17 16:12:18 UTC (rev 342)
@@ -28,9 +28,11 @@
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.nuiton.wikitty.WikittyException;
import org.nuiton.wikitty.WikittyUtil;
import org.nuiton.wikitty.entities.FieldType;
import org.nuiton.wikitty.entities.Wikitty;
+import org.nuiton.wikitty.entities.WikittyExtension;
import javax.servlet.ServletContext;
import javax.servlet.jsp.JspException;
@@ -56,174 +58,210 @@
*/
public class WikittyInput extends SimpleTagSupport implements DynamicAttributes {
- /** to use log facility, just put in your code: log.info(\"...\"); */
- static private Log log = LogFactory.getLog(WikittyInput.class);
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ static private Log log = LogFactory.getLog(WikittyInput.class);
- protected Map<String, Object> dynamicAttribute = new HashMap<String, Object>();
+ protected Map<String, Object> dynamicAttribute = new HashMap<String, Object>();
- protected String name="";
- protected Object defaultValue="";
+ protected String name="";
+ protected Object defaultValue="";
+ protected boolean emptyField = false;
+ protected Wikitty wikitty;
+ protected WikittyExtension extension = null;
+ protected String fqfield="";
- protected Wikitty wikitty;
- protected String fqfield="";
+ public void setDynamicAttribute(String uri, String localName, Object value) throws JspException {
+ dynamicAttribute.put(localName, value);
+ }
- public void setDynamicAttribute(String uri, String localName, Object value) throws JspException {
- dynamicAttribute.put(localName, value);
- }
+ public void setName(String name) {
+ this.name = name;
+ }
- public void setName(String name) {
- this.name = name;
- }
+ public void setDefaultValue(Object defaultValue) {
+ this.defaultValue = defaultValue;
+ }
- public void setDefaultValue(Object defaultValue) {
- this.defaultValue = defaultValue;
- }
+ public void setWikitty(Wikitty wikitty) {
+ this.wikitty = wikitty;
+ }
- public void setWikitty(Wikitty wikitty) {
- this.wikitty = wikitty;
- }
+ public void setExtension(WikittyExtension extension) {
+ this.extension = extension;
+ }
- public void setFqfield(String fqfield) {
- this.fqfield = fqfield;
- }
+ public void setFqfield(String fqfield) {
+ this.fqfield = fqfield;
+ }
- @Override
- public void doTag() throws JspException, IOException {
- // par defaut si pas de name on utilise celui du field
- if (StringUtils.isBlank(name)) {
- name = fqfield;
- }
+ @Override
+ public void doTag() throws JspException, IOException {
+ // par defaut si pas de name on utilise celui du field
+ if (StringUtils.isBlank(name)) {
+ name = fqfield;
+ }
- JspWriter output = getJspContext().getOut();
- PageContext pageContext = (PageContext)getJspContext();
- ServletContext servletContext = pageContext.getServletContext();
- String contextPath = servletContext.getContextPath();
+ JspWriter output = getJspContext().getOut();
+ PageContext pageContext = (PageContext)getJspContext();
+ ServletContext servletContext = pageContext.getServletContext();
+ String contextPath = servletContext.getContextPath();
- String extName = WikittyUtil.getExtensionNameFromFQFieldName(fqfield);
- String fieldName = WikittyUtil.getFieldNameFromFQFieldName(fqfield);
- FieldType field = wikitty.getFieldType(fqfield);
+ String extName = WikittyUtil.getExtensionNameFromFQFieldName(fqfield);
+ String fieldName = WikittyUtil.getFieldNameFromFQFieldName(fqfield);
+ FieldType field = null;
+ try {
+ System.out.println("JE TENTE DE RECUPERER LE TYPE");
+ field = wikitty.getFieldType(fqfield);
+ System.out.println("LE TYPE EXISTE");
+ }
+ catch(Exception e) {
+ System.out.println("LE TYPE N'EXISTE PAS");
+ System.out.println("JE CATCH L'EXCEPTION");
+ if(extension == null) {
+ System.out.println("extension EST NULL");
+ throw new JspException(e);
+ }
+ else {
+ System.out.println("JE RECUPERE LE TYPE DEPUIS L'EXTENSION");
+ field = extension.getFieldType(WikittyUtil.getFieldNameFromFQFieldName(fqfield));
+ emptyField = true;
+ }
+ }
+
- String visible = field.getTagValue("visible");
- if ("false".equals(visible)) {
- // on affiche rien pour ce champs
- return;
- }
- if (field != null) {
- switch(field.getType()) {
- case BINARY:
- inputBinary(output, contextPath, name, wikitty, field, extName, fieldName);
- break;
- case BOOLEAN:
- inputBoolean(output, contextPath, name, wikitty, field, extName, fieldName);
- break;
- case DATE:
- inputDate(output, contextPath, name, wikitty, field, extName, fieldName);
- break;
- case NUMERIC:
- inputNumeric(output, contextPath, name, wikitty, field, extName, fieldName);
- break;
- case STRING:
- if (field.hasAllowed()) {
- inputSelectString(output, contextPath, name, wikitty, field, extName, fieldName);
- } else if (field.isCollection()){
- inputCollectionString(output, contextPath, name, wikitty, field, extName, fieldName);
- } else {
- inputString(output, contextPath, name, wikitty, field, extName, fieldName);
- }
- break;
- case WIKITTY:
- if (field.isCollection()) {
- inputCollectionWikitty(output, contextPath, name, wikitty, field, extName, fieldName);
- } else {
- inputWikitty(output, contextPath, name, wikitty, field, extName, fieldName);
- }
- break;
- }
- String help = field.getTagValue("help");
- if (StringUtils.isNotBlank(help)) {
- /*{ <i class="icon-question-sign" title="<%=help%>"></i>}*/
- }
- } else {
- /*{<div class="alert alert-error"><%=wikitty.getWikittyId()%> doesn't have field '<%=fqfield%>'</div>}*/
- }
- }
+
- protected String getDynamicAttribute() {
- String result = "";
- for (Map.Entry<String, Object> e : dynamicAttribute.entrySet()) {
- result += " " + e.getKey() + "=\"" + e.getValue() + "\"";
- }
- return result;
- }
+ if (field != null) {
+ String visible = field.getTagValue("visible");
+ if ("false".equals(visible)) {
+ // on affiche rien pour ce champs
+ return;
+ }
+
+ switch(field.getType()) {
+ case BINARY:
+ inputBinary(output, contextPath, name, wikitty, field, extName, fieldName);
+ break;
+ case BOOLEAN:
+ inputBoolean(output, contextPath, name, wikitty, field, extName, fieldName);
+ break;
+ case DATE:
+ inputDate(output, contextPath, name, wikitty, field, extName, fieldName);
+ break;
+ case NUMERIC:
+ inputNumeric(output, contextPath, name, wikitty, field, extName, fieldName);
+ break;
+ case STRING:
+ if (field.hasAllowed()) {
+ inputSelectString(output, contextPath, name, wikitty, field, extName, fieldName);
+ } else if (field.isCollection()){
+ inputCollectionString(output, contextPath, name, wikitty, field, extName, fieldName);
+ } else {
+ inputString(output, contextPath, name, wikitty, field, extName, fieldName);
+ }
+ break;
+ case WIKITTY:
+ if (field.isCollection()) {
+ inputCollectionWikitty(output, contextPath, name, wikitty, field, extName, fieldName);
+ } else {
+ inputWikitty(output, contextPath, name, wikitty, field, extName, fieldName);
+ }
+ break;
+ }
+ String help = field.getTagValue("help");
+ if (StringUtils.isNotBlank(help)) {
+ /*{ <i class="icon-question-sign" title="<%=help%>"></i>}*/
+ }
+ } else {
+ /*{<div class="alert alert-error"><%=wikitty.getWikittyId()%> doesn't have field '<%=fqfield%>'</div>}*/
+ }
+ }
+ protected String getDynamicAttribute() {
+ String result = "";
+ for (Map.Entry<String, Object> e : dynamicAttribute.entrySet()) {
+ result += " " + e.getKey() + "=\"" + e.getValue() + "\"";
+ }
+ return result;
+ }
- protected void inputBinary(JspWriter output, String contextPath, String name,
- Wikitty wikitty, FieldType field, String extName , String fieldName)
- throws JspException, IOException {
- /*{<input type="file" name="<%=name%>" <%=getDynamicAttribute()%>/>}*/
- }
- protected void inputBoolean(JspWriter output, String contextPath, String name,
- Wikitty wikitty, FieldType field, String extName , String fieldName)
- throws JspException, IOException {
- boolean value = wikitty.getFieldAsBoolean(extName, fieldName);
- String checked="";
- if (value) {
- checked=" checked";
- }
- /*{<input type="checkbox" name="<%=name%>"<%=checked%><%=getDynamicAttribute()%>/>}*/
- }
+ protected void inputBinary(JspWriter output, String contextPath, String name,
+ Wikitty wikitty, FieldType field, String extName , String fieldName)
+ throws JspException, IOException {
+ /*{<input type="file" name="<%=name%>" <%=getDynamicAttribute()%>/>}*/
+ }
- protected void inputDate(JspWriter output, String contextPath, String name,
- Wikitty wikitty, FieldType field, String extName , String fieldName)
- throws JspException, IOException {
- Date date = wikitty.getFieldAsDate(extName, fieldName);
- String value = "";
- if ("month".equals(field.getTagValue("subtype"))) {
- if (date != null) {
- value = DateFormatUtils.format(date, "MM/yyyy");
- }
- /*{<input class="monthpicker" type="text" name="<%=name%>" value="<%=value%>" <%=getDynamicAttribute()%>/>}*/
- } else if ("time".equals(field.getTagValue("subtype"))) {
- if (date != null) {
- value = DateFormatUtils.format(date, "HH:mm");
- }
- /*{<input class="timepicker" type="text" name="<%=name%>" value="<%=value%>" <%=getDynamicAttribute()%>/>}*/
- } else if ("datetime".equals(field.getTagValue("subtype"))) {
- if (date != null) {
- value = DateFormatUtils.format(date, "dd/MM/yyyy HH:mm");
- }
- /*{<input class="datetimepicker" type="text" name="<%=name%>" value="<%=value%>" <%=getDynamicAttribute()%>/>}*/
- } else {
- if (date != null) {
- value = DateFormatUtils.format(date, "dd/MM/yyyy");
- }
- /*{<input class="datepicker" type="text" name="<%=name%>" value="<%=value%>"<%=getDynamicAttribute()%>/>}*/
- }
- }
+ protected void inputBoolean(JspWriter output, String contextPath, String name,
+ Wikitty wikitty, FieldType field, String extName , String fieldName)
+ throws JspException, IOException {
+ boolean value = false;
+ if(!emptyField)
+ value = wikitty.getFieldAsBoolean(extName, fieldName);
+ String checked="";
+ if (value) {
+ checked=" checked";
+ }
+ /*{<input type="checkbox" name="<%=name%>"<%=checked%><%=getDynamicAttribute()%>/>}*/
+ }
- protected void inputNumeric(JspWriter output, String contextPath, String name,
- Wikitty wikitty, FieldType field, String extName , String fieldName)
- throws JspException, IOException {
- BigDecimal value = wikitty.getFieldAsBigDecimal(extName, fieldName);
- NumberFormat formatter = NumberFormat.getNumberInstance();
- String formattedValue = formatter.format(value);
- /*{<input type="text" name="<%=name%>" value="<%=formattedValue%>"<%=getDynamicAttribute()%>/>}*/
- }
+ protected void inputDate(JspWriter output, String contextPath, String name,
+ Wikitty wikitty, FieldType field, String extName , String fieldName)
+ throws JspException, IOException {
+ Date date = null;
+ if(!emptyField)
+ date = wikitty.getFieldAsDate(extName, fieldName);
+ String value = "";
+ if ("month".equals(field.getTagValue("subtype"))) {
+ if (date != null) {
+ value = DateFormatUtils.format(date, "MM/yyyy");
+ }
+ /*{<input class="monthpicker" type="text" name="<%=name%>" value="<%=value%>" <%=getDynamicAttribute()%>/>}*/
+ } else if ("time".equals(field.getTagValue("subtype"))) {
+ if (date != null) {
+ value = DateFormatUtils.format(date, "HH:mm");
+ }
+ /*{<input class="timepicker" type="text" name="<%=name%>" value="<%=value%>" <%=getDynamicAttribute()%>/>}*/
+ } else if ("datetime".equals(field.getTagValue("subtype"))) {
+ if (date != null) {
+ value = DateFormatUtils.format(date, "dd/MM/yyyy HH:mm");
+ }
+ /*{<input class="datetimepicker" type="text" name="<%=name%>" value="<%=value%>" <%=getDynamicAttribute()%>/>}*/
+ } else {
+ if (date != null) {
+ value = DateFormatUtils.format(date, "dd/MM/yyyy");
+ }
+ /*{<input class="datepicker" type="text" name="<%=name%>" value="<%=value%>"<%=getDynamicAttribute()%>/>}*/
+ }
+ }
- protected void inputString(JspWriter output, String contextPath, String name,
- Wikitty wikitty, FieldType field, String extName , String fieldName)
- throws JspException, IOException {
- String id = wikitty.getWikittyId() + "-" + extName + "-" + fieldName;
- String fieldValue = wikitty.getFieldAsString(extName, fieldName);
- String value = fieldValue !=null ? fieldValue : "";
- if ("monoline".equalsIgnoreCase(field.getSubtype())) {
- /*{<input id="text-<%=id%>" type="text" name="<%=name%>" value="<%=value%>"<%=getDynamicAttribute()%>/>}*/
- if (field.hasChoiceQuery()) {
- String url = contextPath + "/wikitty-json/searchField?q=" + field.getChoiceQuery();
-/*{
+ protected void inputNumeric(JspWriter output, String contextPath, String name,
+ Wikitty wikitty, FieldType field, String extName , String fieldName)
+ throws JspException, IOException {
+ BigDecimal value = new BigDecimal(0);
+ if(!emptyField)
+ value= wikitty.getFieldAsBigDecimal(extName, fieldName);
+ NumberFormat formatter = NumberFormat.getNumberInstance();
+ String formattedValue = formatter.format(value);
+ /*{<input type="text" name="<%=name%>" value="<%=formattedValue%>"<%=getDynamicAttribute()%>/>}*/
+ }
+
+ protected void inputString(JspWriter output, String contextPath, String name,
+ Wikitty wikitty, FieldType field, String extName , String fieldName)
+ throws JspException, IOException {
+ String id = wikitty.getWikittyId() + "-" + extName + "-" + fieldName;
+
+ String fieldValue = "";
+ if(!emptyField)
+ fieldValue = wikitty.getFieldAsString(extName, fieldName);
+ String value = fieldValue !=null ? fieldValue : "";
+ if ("monoline".equalsIgnoreCase(field.getSubtype())) {
+ /*{<input id="text-<%=id%>" type="text" name="<%=name%>" value="<%=value%>"<%=getDynamicAttribute()%>/>}*/
+ if (field.hasChoiceQuery()) {
+ String url = contextPath + "/wikitty-json/searchField?q=" + field.getChoiceQuery();
+ /*{
<script>
$(function() {
$( "#text-<%=id%>" ).autocomplete({
@@ -233,44 +271,48 @@
});
</script>
}*/
- }
- } else {
- /*{<textarea name="<%=name%>"<%=getDynamicAttribute()%>><%=value%></textarea>}*/
- }
- }
+ }
+ } else {
+ /*{<textarea name="<%=name%>"<%=getDynamicAttribute()%>><%=value%></textarea>}*/
+ }
+ }
- protected void inputSelectString(JspWriter output, String contextPath, String name,
- Wikitty wikitty, FieldType field, String extName , String fieldName)
- throws JspException, IOException {
- String id = wikitty.getWikittyId() + "-" + extName + "-" + fieldName;
- String value = wikitty.getFieldAsString(extName, fieldName);
- /*{<select id="text-<%=id%>" name="<%=name%>" <%=getDynamicAttribute()%> }*/
- if (field.isCollection()) {
- /*{ multiple="multiple" }*/
- }
- /*{ >}*/
- List<String> allowedValues = field.getAllowedAsList();
- for (String allowedValue : allowedValues) {
- String selected = "";
- if (allowedValue.equals(value)) {
- selected = "selected";
- }
- /*{<option value="<%=allowedValue%>" <%=selected%>><%=allowedValue%></option>}*/
- }
- /*{</select>}*/
- }
+ protected void inputSelectString(JspWriter output, String contextPath, String name,
+ Wikitty wikitty, FieldType field, String extName , String fieldName)
+ throws JspException, IOException {
+ String id = wikitty.getWikittyId() + "-" + extName + "-" + fieldName;
+ String value = "";
+ if(!emptyField)
+ value = wikitty.getFieldAsString(extName, fieldName);
+ /*{<select id="text-<%=id%>" name="<%=name%>" <%=getDynamicAttribute()%> }*/
+ if (field.isCollection()) {
+ /*{ multiple="multiple" }*/
+ }
+ /*{ >}*/
+ List<String> allowedValues = field.getAllowedAsList();
+ for (String allowedValue : allowedValues) {
+ String selected = "";
+ if (allowedValue.equals(value)) {
+ selected = "selected";
+ }
+ /*{<option value="<%=allowedValue%>" <%=selected%>><%=allowedValue%></option>}*/
+ }
+ /*{</select>}*/
+ }
- protected void inputCollectionString(JspWriter output, String contextPath, String name,
- Wikitty wikitty, FieldType field, String extName , String fieldName)
- throws JspException, IOException {
- String id = wikitty.getWikittyId() + "-" + extName + "-" + fieldName;
- List<String> value = wikitty.getFieldAsList(extName, fieldName, String.class);
+ protected void inputCollectionString(JspWriter output, String contextPath, String name,
+ Wikitty wikitty, FieldType field, String extName , String fieldName)
+ throws JspException, IOException {
+ String id = wikitty.getWikittyId() + "-" + extName + "-" + fieldName;
+ List<String> value = null;
+ if(!emptyField)
+ value = wikitty.getFieldAsList(extName, fieldName, String.class);
- if ("monoline".equalsIgnoreCase(field.getSubtype())) {
- /*{<input id="text-<%=id%>" type="text" name="<%=name%>" value="<%=value%>"<%=getDynamicAttribute()%>/>}*/
- if (field.hasChoiceQuery()) {
- String url = contextPath + "/wikitty-json/searchField?q=" + field.getChoiceQuery();
-/*{
+ if ("monoline".equalsIgnoreCase(field.getSubtype())) {
+ /*{<input id="text-<%=id%>" type="text" name="<%=name%>" value="<%=value%>"<%=getDynamicAttribute()%>/>}*/
+ if (field.hasChoiceQuery()) {
+ String url = contextPath + "/wikitty-json/searchField?q=" + field.getChoiceQuery();
+ /*{
<script>
$(function() {
$( "#text-<%=id%>" ).autocomplete({
@@ -280,38 +322,43 @@
});
</script>
}*/
- }
- } else {
- /*{<textarea name="<%=name%>"<%=getDynamicAttribute()%>><%=value%></textarea>}*/
- }
- }
+ }
+ } else {
+ /*{<textarea name="<%=name%>"<%=getDynamicAttribute()%>><%=value%></textarea>}*/
+ }
+ }
- protected void inputWikitty(JspWriter output, String contextPath, String name,
- Wikitty wikitty, FieldType field, String extName , String fieldName)
- throws JspException, IOException {
- String id = wikitty.getWikittyId() + "-" + extName + "-" + fieldName;
- String value = wikitty.getFieldAsWikitty(extName, fieldName);
- Wikitty wikittyValue = wikitty.getFieldAsWikitty(extName, fieldName, false);
+ protected void inputWikitty(JspWriter output, String contextPath, String name,
+ Wikitty wikitty, FieldType field, String extName , String fieldName)
+ throws JspException, IOException {
+ String id = wikitty.getWikittyId() + "-" + extName + "-" + fieldName;
+ String value = "";
+ if(!emptyField)
+ value = wikitty.getFieldAsWikitty(extName, fieldName);
+
+ Wikitty wikittyValue = null;
+ if(!emptyField)
+ wikittyValue = wikitty.getFieldAsWikitty(extName, fieldName, false);
- String wlabel = "";
- if (wikittyValue != null) {
- wlabel = wikittyValue.toString();
- }
+ String wlabel = "";
+ if (wikittyValue != null) {
+ wlabel = wikittyValue.toString();
+ }
- String wid = "";
- if (value != null) {
- wid = value;
- }
+ String wid = "";
+ if (value != null) {
+ wid = value;
+ }
- String url = "";
- if (field.hasAllowed()) {
- url = contextPath + "/wikitty-json/search?extension=" + field.getAllowed();
- } else if (field.hasAllowedQuery()) {
- url = contextPath + "/wikitty-json/search?query=" + field.getAllowedQuery();
- } else {
- url = contextPath + "/wikitty-json/search?query=";
- }
-/*{
+ String url = "";
+ if (field.hasAllowed()) {
+ url = contextPath + "/wikitty-json/search?extension=" + field.getAllowed();
+ } else if (field.hasAllowedQuery()) {
+ url = contextPath + "/wikitty-json/search?query=" + field.getAllowedQuery();
+ } else {
+ url = contextPath + "/wikitty-json/search?query=";
+ }
+ /*{
<script>
$(function() {
$( "#text-<%=id%>" ).autocompleteByExtension({
@@ -330,52 +377,54 @@
<input type="text" id="text-<%=id%>" value="<%=wlabel%>"<%=getDynamicAttribute()%>/>
<input type="hidden" id="hidden-<%=id%>" name="<%=name%>" value="<%=wid%>"/>
}*/
- }
+ }
- protected void inputCollectionWikitty(JspWriter output, String contextPath, String name,
- Wikitty wikitty, FieldType field, String extName , String fieldName)
- throws JspException, IOException {
- String id = wikitty.getWikittyId() + "-" + extName + "-" + fieldName;
- List<Wikitty> values = wikitty.getFieldAsWikittyList(extName, fieldName, false);
+ protected void inputCollectionWikitty(JspWriter output, String contextPath, String name,
+ Wikitty wikitty, FieldType field, String extName , String fieldName)
+ throws JspException, IOException {
+ String id = wikitty.getWikittyId() + "-" + extName + "-" + fieldName;
+ List<Wikitty> values = null;
+ if(!emptyField)
+ values = wikitty.getFieldAsWikittyList(extName, fieldName, false);
-// String url = contextPath + "/wikitty-json/search?extension=" + field.getAllowed();
- String url = "";
- if (field.hasAllowed()) {
- url = contextPath + "/wikitty-json/search?extension=" + field.getAllowed();
- } else if (field.hasAllowedQuery()) {
- url = contextPath + "/wikitty-json/search?query=" + field.getAllowedQuery();
- } else {
- url = contextPath + "/wikitty-json/search?query=";
- }
+ // String url = contextPath + "/wikitty-json/search?extension=" + field.getAllowed();
+ String url = "";
+ if (field.hasAllowed()) {
+ url = contextPath + "/wikitty-json/search?extension=" + field.getAllowed();
+ } else if (field.hasAllowedQuery()) {
+ url = contextPath + "/wikitty-json/search?query=" + field.getAllowedQuery();
+ } else {
+ url = contextPath + "/wikitty-json/search?query=";
+ }
- String sep = "";
- String prePopulate = "[";
- if (values != null) {
- for (Wikitty w :values) {
- if (w != null) {
- prePopulate += String.format("%s{id:'%s', label:'%s'}", sep,
- StringEscapeUtils.escapeEcmaScript(w.getWikittyId()),
- StringEscapeUtils.escapeEcmaScript(w.toString()));
- sep = ",";
- }
- }
- }
- prePopulate += "]";
-/*{
+ String sep = "";
+ String prePopulate = "[";
+ if (values != null) {
+ for (Wikitty w :values) {
+ if (w != null) {
+ prePopulate += String.format("%s{id:'%s', label:'%s'}", sep,
+ StringEscapeUtils.escapeEcmaScript(w.getWikittyId()),
+ StringEscapeUtils.escapeEcmaScript(w.toString()));
+ sep = ",";
+ }
+ }
+ }
+ prePopulate += "]";
+ /*{
<script type="text/javascript">
$(document).ready(function () {
$("#text-<%=id%>").tokenInput("<%=url%>", {
prePopulate: <%=prePopulate%>,
preventDuplicates: true,
propertyToSearch: "label"
-
+
});
});
</script>
<input type="text" id="text-<%=id%>" name="<%=name%>"<%=getDynamicAttribute()%>/>
}*/
- }
+ }
}
Modified: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-06-14 14:03:04 UTC (rev 341)
+++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-06-17 16:12:18 UTC (rev 342)
@@ -28,9 +28,33 @@
<h1>${title}</h1>
<form class="well form-inline" method="GET">
- Nom du projet : <input class="input-large" type="text"
- name="projectname" value="${param.projectname}"
- placeholder="project name" /> <input type="submit" class="btn" />
+
+ <div class="control-group">
+ Project Name :
+ <div class="controls" style="display: inline">
+
+ <script>
+ $(function() {
+ $( "#project_text" ).autocompleteByExtension({
+ source: "/chorem/wikitty-json/search?extension=Project",
+ minLength: 2,
+ select: function( event, ui ) {
+ $( "#project_text" ).val( ui.item.label );
+ $( "#project_hidden" ).val( ui.item.id );
+
+ return false;
+ }
+ });
+ });
+ </script>
+
+ <input type="text" id="project_text" name="project_name"
+ value="${param.project_name}" placeholder="project name" /> <input
+ type="hidden" id="project_hidden" name="project_id" value="" /> <input
+ type="submit" class="btn" />
+ </div>
+ </div>
+
</form>
<c:choose>
<c:when test="${projects.size() >= 1}">
@@ -82,30 +106,61 @@
</table>
- Début : ${q.beginDate}<br />
- Fin : <w:display wikitty="${q.wikitty}" fqfield="Interval.endDate"
- label="" />
+
+
+
+ <p>
+ Début : ${q.beginDate}<br /> Fin :
+ <w:display wikitty="${q.wikitty}" fqfield="Interval.endDate"
+ label="" />
+ </p>
<p>Liste des tâches :</p>
- <c:forEach items="${taskMap}" var="entry">
+ <c:forEach items="${taskMap}" var="entry">
<c:if test="${entry.key.equals(q)}">
- <ul>
- <c:forEach items="${entry.value}" var="task">
- <li>${task.name} : ${task.description}</li>
- </c:forEach>
+ <ul>
+ <c:forEach items="${entry.value}" var="task">
+ <li><a
+ href="<c:url value="/wikitty/view/${task.wikittyId}"/>">${task.name}
+ : ${task.description}</a></li>
+ </c:forEach>
+ </ul>
</c:if>
- </ul>
+
</c:forEach>
+
+ <c:forEach items="${extMap}" var="entry">
+ <c:if test="${entry.key.equals(q)}">
+ <c:if test="${entry.value != null}">
+ ${entry.value.fieldNames}
+ <c:forEach items="${entry.value.fieldNames}" var="field">
+ ${field}
+ <div class="control-group">
+ <label class="control-label">${fieldName}</label>
+ <div class="controls">
+ <w:input wikitty="${q.wikitty}"
+ fqfield="${entry.value.name}.${field}" extension="${entry.value}" />
+ </div>
+ </div>
+ </c:forEach>
+ <input type="button" value="Tranformer en ${entry.value.name}" />
+
+ </c:if>
+ </c:if>
+
+
+
+ </c:forEach>
</c:forEach>
</c:when>
<c:otherwise>
<c:if
- test="${param.projectname != null && param.projectname.length() != 0 }">
-Projet inexistant
-</c:if>
+ test="${param.project_id != null && param.projectname.length() != 0 }">
+ Projet inexistant
+ </c:if>
</c:otherwise>
Modified: trunk/chorem-webmotion/src/main/webapp/WEB-INF/wikitty.tld
===================================================================
(Binary files differ)
1
0
r341 - in trunk/chorem-webmotion/src/main: java/org/chorem/webmotion/actions/project webapp/WEB-INF/jsp
by meynier@users.chorem.org 14 Jun '13
by meynier@users.chorem.org 14 Jun '13
14 Jun '13
Author: meynier
Date: 2013-06-14 16:03:04 +0200 (Fri, 14 Jun 2013)
New Revision: 341
Url: http://chorem.org/projects/chorem/repository/revisions/341
Log:
enhanced the prototype of project dashboard (quotations and tasks)
Modified:
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java
trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp
Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-06-13 15:33:58 UTC (rev 340)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-06-14 14:03:04 UTC (rev 341)
@@ -1,5 +1,8 @@
package org.chorem.webmotion.actions.project;
+import java.util.HashMap;
+import java.util.List;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.debux.webmotion.server.WebMotionController;
@@ -8,31 +11,80 @@
import org.debux.webmotion.server.render.Render;
import org.chorem.entities.Quotation;
import org.chorem.entities.Project;
+import org.chorem.entities.Task;
import org.nuiton.wikitty.query.WikittyQuery;
import org.nuiton.wikitty.query.WikittyQueryMaker;
import org.nuiton.wikitty.query.WikittyQueryResult;
public class DashboardProjectAction extends WebMotionController {
- /** to use log facility, just put in your code: log.info(\"...\"); */
- static private Log log = LogFactory.getLog(DashboardProjectAction.class);
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ static private Log log = LogFactory.getLog(DashboardProjectAction.class);
- public Render projectFilter(ChoremClient client, String id) {
-
- WikittyQuery projectQuery = new WikittyQueryMaker()
- .eq(Project.ELEMENT_FIELD_PROJECT_NAME, id)
- .end();
+ public Render projectFilter(ChoremClient client, String id) {
- WikittyQueryResult<Project> result =
- client.findAllByQuery(Project.class, projectQuery);
-
- System.out.println(result);
+ WikittyQueryResult<Project> projectResult = null;
+ WikittyQueryResult<Quotation> quotationResult = null;
+ WikittyQueryResult<Task> taskResult = null;
+ HashMap<Quotation, List<Task>> taskMap = new HashMap<Quotation, List<Task>>();
+
+ //Fetch the project form the name (if it has been requested)
+ if(id != null) {
+ WikittyQuery projectQuery = new WikittyQueryMaker()
+ .eq(Project.ELEMENT_FIELD_PROJECT_NAME, id)
+ .end();
+
+ projectResult = client.findAllByQuery(Project.class, projectQuery);
+
+ //Fetch the quotations form the project (if there is one)
+ if(projectResult.size() != 0) {
+ for(Project project : projectResult.getAll()) {
+ WikittyQuery quotationQuery = new WikittyQueryMaker()
+ .eq(Quotation.ELEMENT_FIELD_QUOTATION_PROJECT, project)
+ .end();
+
+ quotationResult = client.findAllByQuery(Quotation.class, quotationQuery);
+
+
+ }
+
+ }
+
+ //Fetch the tasks form the quotations (if there are some)
+ if(quotationResult != null) {
+ for(Quotation quote : quotationResult.getAll()) {
+ WikittyQuery taskQuery = new WikittyQueryMaker()
+ .eq(Task.ELEMENT_FIELD_TASK_QUOTATION, quote)
+ .end();
+
+ taskResult = client.findAllByQuery(Task.class, taskQuery);
+ taskMap.put(quote, taskResult.getAll());
+
+
+ }
+
+ }
+
+ }
+ System.out.println(taskMap);
- return renderView("dashboardSingleProject.jsp",
- "title", "Tableau de bord projet", "projects", result.getAll());
- }
-
- public Render requestProject(ChoremClient client, String projectname) {
- return projectFilter(client, projectname);
- }
+ if(projectResult == null) {
+ return renderView("dashboardSingleProject.jsp",
+ "title", "Tableau de bord projet", "projects", null,"quotations",null);
+ }
+ else if(quotationResult == null) {
+ return renderView("dashboardSingleProject.jsp",
+ "title", "Tableau de bord projet", "projects", projectResult.getAll(),
+ "quotations", null);
+ }
+ else {
+ return renderView("dashboardSingleProject.jsp",
+ "title", "Tableau de bord projet", "projects", projectResult.getAll(),
+ "quotations", quotationResult.getAll(), "taskMap", taskMap);
+ }
+ }
+
+ public Render requestProject(ChoremClient client, String projectname) {
+ return projectFilter(client, projectname);
+ }
}
Modified: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-06-13 15:33:58 UTC (rev 340)
+++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-06-14 14:03:04 UTC (rev 341)
@@ -21,44 +21,94 @@
#L%
--%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%>
<h1>${title}</h1>
<form class="well form-inline" method="GET">
-Nom du projet : <input class="input-large" type="text" name="projectname" value="${param.projectname}" placeholder="project name"/>
-<input type="submit" class="btn"/>
+ Nom du projet : <input class="input-large" type="text"
+ name="projectname" value="${param.projectname}"
+ placeholder="project name" /> <input type="submit" class="btn" />
</form>
<c:choose>
-<c:when test="${projects.size() == 1}">
-<%//Project table generation %>
-<table class="table table-striped table-bordered table-condensed">
- <thead>
- <tr>
- <th>Project</th>
- <th>Description</th>
- </tr>
- </thead>
- <c:forEach var="p" items="${projects}">
- <tbody>
- <tr>
- <td>${p.name}</td>
- <td>${p.description}</td>
- </tr>
- </tbody>
- </c:forEach>
- </table>
-</c:when>
+ <c:when test="${projects.size() >= 1}">
-<c:otherwise>
-<c:if test="${param.projectname.length() != 0 }">
+
+ <c:forEach var="p" items="${projects}">
+ <h2>${p.name}</h2>
+ <p>${p.description}</p>
+ </c:forEach>
+
+
+
+
+ <c:forEach var="q" items="${quotations}">
+ <table class="table table-striped table-bordered table-condensed">
+ <thead>
+ <tr>
+ <th>Devis</th>
+ <th>Responsable Code Lutin</th>
+ <th>Responsable entreprise</th>
+ <th>Estimated days</th>
+ <th>Conversion hope</th>
+ <th>Hoped price day</th>
+ <th>Amount</th>
+ </tr>
+ </thead>
+ </thead>
+
+ <tbody>
+ <tr>
+ <td><w:display wikitty="${q.wikitty}"
+ fqfield="Quotation.description" label="" /></td>
+ <td><w:display wikitty="${q.wikitty}"
+ fqfield="Quotation.supplier" label="" /></td>
+ <td><w:display wikitty="${q.wikitty}"
+ fqfield="Quotation.customer" label="" /></td>
+ <td class="number"><w:display wikitty="${q.wikitty}"
+ fqfield="Quotation.estimatedDays" label="" /></td>
+ <td class="percent"><w:display wikitty="${q.wikitty}"
+ fqfield="Quotation.conversionHope" label="" /></td>
+ <td class="currency"><f:formatNumber type="currency"
+ value="${q.amount / q.estimatedDays}" /></td>
+ <td class="currency"><w:display wikitty="${q.wikitty}"
+ fqfield="Quotation.amount" label="" /></td>
+ </td>
+ </tr>
+ </tbody>
+
+
+
+ </table>
+ Début : ${q.beginDate}<br />
+ Fin : <w:display wikitty="${q.wikitty}" fqfield="Interval.endDate"
+ label="" />
+ <p>Liste des tâches :</p>
+ <c:forEach items="${taskMap}" var="entry">
+
+ <c:if test="${entry.key.equals(q)}">
+ <ul>
+ <c:forEach items="${entry.value}" var="task">
+ <li>${task.name} : ${task.description}</li>
+ </c:forEach>
+ </c:if>
+ </ul>
+
+
+ </c:forEach>
+ </c:forEach>
+ </c:when>
+
+ <c:otherwise>
+ <c:if
+ test="${param.projectname != null && param.projectname.length() != 0 }">
Projet inexistant
</c:if>
-</c:otherwise>
+ </c:otherwise>
</c:choose>
1
0
r340 - in trunk/chorem-webmotion/src/main: java/org/chorem/webmotion/actions java/org/chorem/webmotion/actions/project webapp/WEB-INF/jsp
by meynier@users.chorem.org 13 Jun '13
by meynier@users.chorem.org 13 Jun '13
13 Jun '13
Author: meynier
Date: 2013-06-13 17:33:58 +0200 (Thu, 13 Jun 2013)
New Revision: 340
Url: http://chorem.org/projects/chorem/repository/revisions/340
Log:
added missing files for project dashboard
Added:
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/
trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java
trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp
Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java
===================================================================
--- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java (rev 0)
+++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-06-13 15:33:58 UTC (rev 340)
@@ -0,0 +1,38 @@
+package org.chorem.webmotion.actions.project;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.debux.webmotion.server.WebMotionController;
+import org.chorem.ChoremClient;
+import org.debux.webmotion.server.call.Call;
+import org.debux.webmotion.server.render.Render;
+import org.chorem.entities.Quotation;
+import org.chorem.entities.Project;
+import org.nuiton.wikitty.query.WikittyQuery;
+import org.nuiton.wikitty.query.WikittyQueryMaker;
+import org.nuiton.wikitty.query.WikittyQueryResult;
+
+public class DashboardProjectAction extends WebMotionController {
+
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ static private Log log = LogFactory.getLog(DashboardProjectAction.class);
+
+ public Render projectFilter(ChoremClient client, String id) {
+
+ WikittyQuery projectQuery = new WikittyQueryMaker()
+ .eq(Project.ELEMENT_FIELD_PROJECT_NAME, id)
+ .end();
+
+ WikittyQueryResult<Project> result =
+ client.findAllByQuery(Project.class, projectQuery);
+
+ System.out.println(result);
+
+ return renderView("dashboardSingleProject.jsp",
+ "title", "Tableau de bord projet", "projects", result.getAll());
+ }
+
+ public Render requestProject(ChoremClient client, String projectname) {
+ return projectFilter(client, projectname);
+ }
+}
Added: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp
===================================================================
--- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp (rev 0)
+++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-06-13 15:33:58 UTC (rev 340)
@@ -0,0 +1,73 @@
+<%--
+ #%L
+ Chorem webmotion
+ $Id:$
+ $HeadURL:$
+ %%
+ Copyright (C) 2011 - 2012 CodeLutin
+ %%
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ #L%
+ --%>
+<%@page contentType="text/html" pageEncoding="UTF-8"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
+<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%>
+
+<h1>${title}</h1>
+<form class="well form-inline" method="GET">
+Nom du projet : <input class="input-large" type="text" name="projectname" value="${param.projectname}" placeholder="project name"/>
+<input type="submit" class="btn"/>
+</form>
+<c:choose>
+<c:when test="${projects.size() == 1}">
+<%//Project table generation %>
+<table class="table table-striped table-bordered table-condensed">
+ <thead>
+ <tr>
+ <th>Project</th>
+ <th>Description</th>
+ </tr>
+ </thead>
+ <c:forEach var="p" items="${projects}">
+ <tbody>
+ <tr>
+ <td>${p.name}</td>
+ <td>${p.description}</td>
+ </tr>
+ </tbody>
+ </c:forEach>
+ </table>
+</c:when>
+
+<c:otherwise>
+<c:if test="${param.projectname.length() != 0 }">
+Projet inexistant
+</c:if>
+
+
+</c:otherwise>
+
+
+</c:choose>
+
+
+
+
+
+
+
+
+
1
0