Added age chart. Refactored code.
This commit is contained in:
parent
b8eecdd60f
commit
de605e2a55
13 changed files with 1201 additions and 311 deletions
|
@ -24,6 +24,8 @@ import java.sql.DriverManager;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.april.agirstatool.core.AgirStatoolException;
|
import org.april.agirstatool.core.AgirStatoolException;
|
||||||
|
@ -241,4 +243,30 @@ public final class SQLUtils
|
||||||
//
|
//
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To date time.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @return the local date time
|
||||||
|
*/
|
||||||
|
public static LocalDateTime toLocalDateTime(final java.sql.Timestamp source)
|
||||||
|
{
|
||||||
|
LocalDateTime result;
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long seconds = source.getTime() / 1000;
|
||||||
|
long nanos = (source.getTime() - seconds * 1000) * 1000000;
|
||||||
|
result = LocalDateTime.ofEpochSecond(seconds, (int) nanos, ZoneOffset.UTC);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,262 @@ public class AgirStatool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch issue open closed dates.
|
||||||
|
*
|
||||||
|
* @param project
|
||||||
|
* the project
|
||||||
|
* @return the date count map
|
||||||
|
* @throws AgirStatoolException
|
||||||
|
* the agir statool exception
|
||||||
|
*/
|
||||||
|
public Issues fetchIssue(final Project project) throws AgirStatoolException
|
||||||
|
{
|
||||||
|
Issues result;
|
||||||
|
|
||||||
|
result = new Issues();
|
||||||
|
|
||||||
|
//
|
||||||
|
PreparedStatement statement = null;
|
||||||
|
ResultSet resultSet = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StringList subSql = new StringList();
|
||||||
|
if (project.getType() == Project.Type.CONSOLIDATED)
|
||||||
|
{
|
||||||
|
subSql.append("select ");
|
||||||
|
subSql.append(" id ");
|
||||||
|
subSql.append("from ");
|
||||||
|
subSql.append(" projects as childProject ");
|
||||||
|
subSql.append("where ");
|
||||||
|
subSql.append(" (childProject.id=" + project.getId() + " or childProject.parent_id=" + project.getId() + ")");
|
||||||
|
subSql.append(" and childProject.status=1 and childProject.is_public=1");
|
||||||
|
}
|
||||||
|
else if (project.getType() == Project.Type.ROOT)
|
||||||
|
{
|
||||||
|
subSql.append("select ");
|
||||||
|
subSql.append(" id ");
|
||||||
|
subSql.append("from ");
|
||||||
|
subSql.append(" projects as childProject ");
|
||||||
|
subSql.append("where ");
|
||||||
|
subSql.append(" childProject.status=1 and childProject.is_public=1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subSql.append(project.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
StringList sql = new StringList();
|
||||||
|
sql.append("SELECT");
|
||||||
|
sql.append(" id, ");
|
||||||
|
sql.append(" project_id, ");
|
||||||
|
sql.append(" created_on, ");
|
||||||
|
sql.append(" closed_on ");
|
||||||
|
sql.append("FROM ");
|
||||||
|
sql.append(" issues ");
|
||||||
|
sql.append("WHERE ");
|
||||||
|
sql.append(" project_id in (" + subSql.toString() + ") ");
|
||||||
|
|
||||||
|
// System.out.println(sql.toStringSeparatedBy("\n"));
|
||||||
|
|
||||||
|
this.connection.setAutoCommit(true);
|
||||||
|
statement = this.connection.prepareStatement(sql.toString());
|
||||||
|
resultSet = statement.executeQuery();
|
||||||
|
|
||||||
|
while (resultSet.next())
|
||||||
|
{
|
||||||
|
int id = resultSet.getInt(1);
|
||||||
|
int projectId = resultSet.getInt(2);
|
||||||
|
LocalDateTime createdOn = SQLUtils.toLocalDateTime(resultSet.getTimestamp(3));
|
||||||
|
LocalDateTime closedOn = SQLUtils.toLocalDateTime(resultSet.getTimestamp(4));
|
||||||
|
|
||||||
|
Issue issue = new Issue(id, projectId, createdOn, closedOn);
|
||||||
|
|
||||||
|
result.add(issue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException exception)
|
||||||
|
{
|
||||||
|
throw new AgirStatoolException("Error fetching day closed count: " + exception.getMessage(), exception);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SQLUtils.closeQuietly(statement, resultSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List projects extended.
|
||||||
|
*
|
||||||
|
* @return the projects
|
||||||
|
* @throws AgirStatoolException
|
||||||
|
* the agir statool exception
|
||||||
|
*/
|
||||||
|
public Projects fetchProjectsWithoutSubStats() throws AgirStatoolException
|
||||||
|
{
|
||||||
|
Projects result;
|
||||||
|
|
||||||
|
result = fetchProjectsWithStats(Project.Type.ALONE);
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List projects with stats.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the type
|
||||||
|
* @return the projects
|
||||||
|
* @throws AgirStatoolException
|
||||||
|
* the agir statool exception
|
||||||
|
*/
|
||||||
|
public Projects fetchProjectsWithStats(final Project.Type type) throws AgirStatoolException
|
||||||
|
{
|
||||||
|
Projects result;
|
||||||
|
|
||||||
|
result = new Projects();
|
||||||
|
|
||||||
|
//
|
||||||
|
PreparedStatement statement = null;
|
||||||
|
ResultSet resultSet = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StringList subSql = new StringList();
|
||||||
|
if (type == Project.Type.CONSOLIDATED)
|
||||||
|
{
|
||||||
|
subSql.append("select ");
|
||||||
|
subSql.append(" id ");
|
||||||
|
subSql.append("from ");
|
||||||
|
subSql.append(" projects as childProject ");
|
||||||
|
subSql.append("where ");
|
||||||
|
subSql.append(" (childProject.id=currentProject.id or childProject.parent_id=currentProject.id)");
|
||||||
|
subSql.append(" and childProject.status=1 and childProject.is_public=1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subSql.append("currentProject.id");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringList sql = new StringList();
|
||||||
|
sql.append("SELECT");
|
||||||
|
sql.append(" id,");
|
||||||
|
sql.append(" identifier,");
|
||||||
|
sql.append(" name,");
|
||||||
|
sql.append(" parent_id,");
|
||||||
|
sql.append(" (select count(*) from projects as subproject where subproject.parent_id=currentProject.id and subproject.status = 1 and subproject.is_public = 1) as child_count, ");
|
||||||
|
sql.append(" updated_on,");
|
||||||
|
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ")) as issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 1) as new_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 2) as ongoing_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 3) as resolved_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 5) as closed_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 6) as rejected_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 7) as confirmed_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id=15) as maybe_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id=16) as waiting_issue_count, ");
|
||||||
|
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.assigned_to_id is null) as unassigned_issue_count,");
|
||||||
|
sql.append(
|
||||||
|
" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 1 and issues.assigned_to_id is null) as unassigned_new_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
||||||
|
+ ") and issues.status_id= 2 and issues.assigned_to_id is null) as unassigned_ongoing_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
||||||
|
+ ") and issues.status_id= 3 and issues.assigned_to_id is null) as unassigned_resolved_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
||||||
|
+ ") and issues.status_id= 5 and issues.assigned_to_id is null) as unassigned_closed_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
||||||
|
+ ") and issues.status_id= 6 and issues.assigned_to_id is null) as unassigned_rejected_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
||||||
|
+ ") and issues.status_id= 7 and issues.assigned_to_id is null) as unassigned_confirmed_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
||||||
|
+ ") and issues.status_id=15 and issues.assigned_to_id is null) as unassigned_maybe_issue_count,");
|
||||||
|
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
||||||
|
+ ") and issues.status_id=16 and issues.assigned_to_id is null) as unassigned_waiting_issue_count, ");
|
||||||
|
sql.append(" (select min(created_on) from issues where issues.project_id in (" + subSql.toString() + ")) as first_issue_create, ");
|
||||||
|
sql.append(" (select max(updated_on) from issues where issues.project_id in (" + subSql.toString() + ")) as last_issue_update ");
|
||||||
|
|
||||||
|
sql.append("FROM ");
|
||||||
|
sql.append(" projects as currentProject ");
|
||||||
|
sql.append("WHERE ");
|
||||||
|
sql.append(" currentProject.status=1 and currentProject.is_public=1;");
|
||||||
|
|
||||||
|
// System.out.println(sql.toStringSeparatedBy("\n"));
|
||||||
|
|
||||||
|
this.connection.setAutoCommit(true);
|
||||||
|
statement = this.connection.prepareStatement(sql.toString());
|
||||||
|
resultSet = statement.executeQuery();
|
||||||
|
|
||||||
|
while (resultSet.next())
|
||||||
|
{
|
||||||
|
long id = resultSet.getLong(1);
|
||||||
|
String identifier = resultSet.getString(2);
|
||||||
|
String name = resultSet.getString(3);
|
||||||
|
Long parentId = SQLUtils.getNullableLong(resultSet, 4);
|
||||||
|
|
||||||
|
Project project = new Project(id, identifier, name, parentId);
|
||||||
|
project.setChildCount(resultSet.getLong(5));
|
||||||
|
project.setLastUpdate(SQLUtils.toLocalDateTime(resultSet.getTimestamp(6)));
|
||||||
|
|
||||||
|
project.issueStats().setCount(resultSet.getLong(7));
|
||||||
|
project.issueStats().setNewCount(resultSet.getLong(8));
|
||||||
|
project.issueStats().setOngoingCount(resultSet.getLong(9));
|
||||||
|
project.issueStats().setResolvedCount(resultSet.getLong(10));
|
||||||
|
project.issueStats().setClosedCount(resultSet.getLong(11));
|
||||||
|
project.issueStats().setRejectedCount(resultSet.getLong(12));
|
||||||
|
project.issueStats().setConfirmedCount(resultSet.getLong(13));
|
||||||
|
project.issueStats().setMaybeCount(resultSet.getLong(14));
|
||||||
|
project.issueStats().setWaitingCount(resultSet.getLong(15));
|
||||||
|
|
||||||
|
project.issueStats().setUnassignedCount(resultSet.getLong(16));
|
||||||
|
project.issueStats().setUnassignedNewCount(resultSet.getLong(17));
|
||||||
|
project.issueStats().setUnassignedOngoingCount(resultSet.getLong(18));
|
||||||
|
project.issueStats().setUnassignedResolvedCount(resultSet.getLong(19));
|
||||||
|
project.issueStats().setUnassignedClosedCount(resultSet.getLong(20));
|
||||||
|
project.issueStats().setUnassignedRejectedCount(resultSet.getLong(21));
|
||||||
|
project.issueStats().setUnassignedConfirmedCount(resultSet.getLong(22));
|
||||||
|
project.issueStats().setUnassignedMaybeCount(resultSet.getLong(23));
|
||||||
|
project.issueStats().setUnassignedWaitingCount(resultSet.getLong(24));
|
||||||
|
|
||||||
|
project.issueStats().setFirstCreate(SQLUtils.toLocalDateTime(resultSet.getTimestamp(25)));
|
||||||
|
project.issueStats().setLastUpdate(SQLUtils.toLocalDateTime(resultSet.getTimestamp(26)));
|
||||||
|
|
||||||
|
result.add(project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException exception)
|
||||||
|
{
|
||||||
|
throw new AgirStatoolException("Error reading projects extended: " + exception.getMessage(), exception);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SQLUtils.closeQuietly(statement, resultSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List projects consolidated.
|
||||||
|
*
|
||||||
|
* @return the projects
|
||||||
|
* @throws AgirStatoolException
|
||||||
|
* the agir statool exception
|
||||||
|
*/
|
||||||
|
public Projects fetchProjectsWithSubStats() throws AgirStatoolException
|
||||||
|
{
|
||||||
|
Projects result;
|
||||||
|
|
||||||
|
result = fetchProjectsWithStats(Project.Type.CONSOLIDATED);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch week concluded count.
|
* Fetch week concluded count.
|
||||||
*
|
*
|
||||||
|
@ -247,7 +503,7 @@ public class AgirStatool
|
||||||
* @throws AgirStatoolException
|
* @throws AgirStatoolException
|
||||||
* the agir statool exception
|
* the agir statool exception
|
||||||
*/
|
*/
|
||||||
public DateCountMap fetchWeekConcludedCount(final Project project) throws AgirStatoolException
|
public DateCountMap fetchWeekClosedOnCount(final Project project) throws AgirStatoolException
|
||||||
{
|
{
|
||||||
DateCountMap result;
|
DateCountMap result;
|
||||||
|
|
||||||
|
@ -458,7 +714,7 @@ public class AgirStatool
|
||||||
|
|
||||||
result = new Project(id, identifier, name, parentId);
|
result = new Project(id, identifier, name, parentId);
|
||||||
result.setChildCount(resultSet.getLong(5));
|
result.setChildCount(resultSet.getLong(5));
|
||||||
result.setLastUpdate(AgirStatoolUtils.toLocaleDateTime(resultSet.getTimestamp(6)));
|
result.setLastUpdate(SQLUtils.toLocalDateTime(resultSet.getTimestamp(6)));
|
||||||
result.issueStats().setCount(resultSet.getLong(7));
|
result.issueStats().setCount(resultSet.getLong(7));
|
||||||
result.issueStats().setNewCount(resultSet.getLong(8));
|
result.issueStats().setNewCount(resultSet.getLong(8));
|
||||||
result.issueStats().setOngoingCount(resultSet.getLong(9));
|
result.issueStats().setOngoingCount(resultSet.getLong(9));
|
||||||
|
@ -468,8 +724,8 @@ public class AgirStatool
|
||||||
result.issueStats().setConfirmedCount(resultSet.getLong(13));
|
result.issueStats().setConfirmedCount(resultSet.getLong(13));
|
||||||
result.issueStats().setMaybeCount(resultSet.getLong(14));
|
result.issueStats().setMaybeCount(resultSet.getLong(14));
|
||||||
result.issueStats().setWaitingCount(resultSet.getLong(15));
|
result.issueStats().setWaitingCount(resultSet.getLong(15));
|
||||||
result.issueStats().setFirstCreate(AgirStatoolUtils.toLocaleDateTime(resultSet.getTimestamp(16)));
|
result.issueStats().setFirstCreate(SQLUtils.toLocalDateTime(resultSet.getTimestamp(16)));
|
||||||
result.issueStats().setLastUpdate(AgirStatoolUtils.toLocaleDateTime(resultSet.getTimestamp(17)));
|
result.issueStats().setLastUpdate(SQLUtils.toLocalDateTime(resultSet.getTimestamp(17)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SQLException exception)
|
catch (SQLException exception)
|
||||||
|
@ -587,7 +843,7 @@ public class AgirStatool
|
||||||
|
|
||||||
Project project = new Project(id, identifier, name, parentId);
|
Project project = new Project(id, identifier, name, parentId);
|
||||||
project.setChildCount(resultSet.getLong(5));
|
project.setChildCount(resultSet.getLong(5));
|
||||||
project.setLastUpdate(AgirStatoolUtils.toLocaleDateTime(resultSet.getTimestamp(6)));
|
project.setLastUpdate(SQLUtils.toLocalDateTime(resultSet.getTimestamp(6)));
|
||||||
|
|
||||||
result.add(project);
|
result.add(project);
|
||||||
}
|
}
|
||||||
|
@ -638,13 +894,17 @@ public class AgirStatool
|
||||||
|
|
||||||
// Fill created and concluded issues history.
|
// Fill created and concluded issues history.
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
Issues issues = fetchIssue(result);
|
||||||
|
result.issues().addAll(issues);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
DateCountMap map = fetchWeekCreatedCount(result);
|
DateCountMap map = fetchWeekCreatedCount(result);
|
||||||
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, result.issueStats().getFirstCreate().toLocalDate());
|
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, result.issueStats().getFirstCreate().toLocalDate());
|
||||||
result.issueStats().setWeekCreatedIssueCounts(counts);
|
result.issueStats().setWeekCreatedIssueCounts(counts);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
DateCountMap map = fetchWeekConcludedCount(result);
|
DateCountMap map = fetchWeekClosedOnCount(result);
|
||||||
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, result.issueStats().getFirstCreate().toLocalDate());
|
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, result.issueStats().getFirstCreate().toLocalDate());
|
||||||
result.issueStats().setWeekConcludedIssueCounts(counts);
|
result.issueStats().setWeekConcludedIssueCounts(counts);
|
||||||
}
|
}
|
||||||
|
@ -654,13 +914,17 @@ public class AgirStatool
|
||||||
logger.debug("Fetching Created/Closed history for " + project.getName());
|
logger.debug("Fetching Created/Closed history for " + project.getName());
|
||||||
if (project.hasIssue())
|
if (project.hasIssue())
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
Issues issues = fetchIssue(project);
|
||||||
|
project.issues().addAll(issues);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
DateCountMap map = fetchWeekCreatedCount(project);
|
DateCountMap map = fetchWeekCreatedCount(project);
|
||||||
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, project.issueStats().getFirstCreate().toLocalDate());
|
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, project.issueStats().getFirstCreate().toLocalDate());
|
||||||
project.issueStats().setWeekCreatedIssueCounts(counts);
|
project.issueStats().setWeekCreatedIssueCounts(counts);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
DateCountMap map = fetchWeekConcludedCount(project);
|
DateCountMap map = fetchWeekClosedOnCount(project);
|
||||||
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, project.issueStats().getFirstCreate().toLocalDate());
|
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, project.issueStats().getFirstCreate().toLocalDate());
|
||||||
project.issueStats().setWeekConcludedIssueCounts(counts);
|
project.issueStats().setWeekConcludedIssueCounts(counts);
|
||||||
}
|
}
|
||||||
|
@ -687,175 +951,6 @@ public class AgirStatool
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* List projects extended.
|
|
||||||
*
|
|
||||||
* @return the projects
|
|
||||||
* @throws AgirStatoolException
|
|
||||||
* the agir statool exception
|
|
||||||
*/
|
|
||||||
public Projects fetchProjectsWithoutSubStats() throws AgirStatoolException
|
|
||||||
{
|
|
||||||
Projects result;
|
|
||||||
|
|
||||||
result = fetchProjectsWithStats(Project.Type.ALONE);
|
|
||||||
//
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List projects with stats.
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* the type
|
|
||||||
* @return the projects
|
|
||||||
* @throws AgirStatoolException
|
|
||||||
* the agir statool exception
|
|
||||||
*/
|
|
||||||
public Projects fetchProjectsWithStats(final Project.Type type) throws AgirStatoolException
|
|
||||||
{
|
|
||||||
Projects result;
|
|
||||||
|
|
||||||
result = new Projects();
|
|
||||||
|
|
||||||
//
|
|
||||||
PreparedStatement statement = null;
|
|
||||||
ResultSet resultSet = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StringList subSql = new StringList();
|
|
||||||
if (type == Project.Type.CONSOLIDATED)
|
|
||||||
{
|
|
||||||
subSql.append("select ");
|
|
||||||
subSql.append(" id ");
|
|
||||||
subSql.append("from ");
|
|
||||||
subSql.append(" projects as childProject ");
|
|
||||||
subSql.append("where ");
|
|
||||||
subSql.append(" (childProject.id=currentProject.id or childProject.parent_id=currentProject.id)");
|
|
||||||
subSql.append(" and childProject.status=1 and childProject.is_public=1");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
subSql.append("currentProject.id");
|
|
||||||
}
|
|
||||||
|
|
||||||
StringList sql = new StringList();
|
|
||||||
sql.append("SELECT");
|
|
||||||
sql.append(" id,");
|
|
||||||
sql.append(" identifier,");
|
|
||||||
sql.append(" name,");
|
|
||||||
sql.append(" parent_id,");
|
|
||||||
sql.append(" (select count(*) from projects as subproject where subproject.parent_id=currentProject.id and subproject.status = 1 and subproject.is_public = 1) as child_count, ");
|
|
||||||
sql.append(" updated_on,");
|
|
||||||
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ")) as issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 1) as new_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 2) as ongoing_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 3) as resolved_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 5) as closed_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 6) as rejected_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 7) as confirmed_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id=15) as maybe_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id=16) as waiting_issue_count, ");
|
|
||||||
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.assigned_to_id is null) as unassigned_issue_count,");
|
|
||||||
sql.append(
|
|
||||||
" (select count(*) from issues where issues.project_id in (" + subSql.toString() + ") and issues.status_id= 1 and issues.assigned_to_id is null) as unassigned_new_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
|
||||||
+ ") and issues.status_id= 2 and issues.assigned_to_id is null) as unassigned_ongoing_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
|
||||||
+ ") and issues.status_id= 3 and issues.assigned_to_id is null) as unassigned_resolved_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
|
||||||
+ ") and issues.status_id= 5 and issues.assigned_to_id is null) as unassigned_closed_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
|
||||||
+ ") and issues.status_id= 6 and issues.assigned_to_id is null) as unassigned_rejected_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
|
||||||
+ ") and issues.status_id= 7 and issues.assigned_to_id is null) as unassigned_confirmed_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
|
||||||
+ ") and issues.status_id=15 and issues.assigned_to_id is null) as unassigned_maybe_issue_count,");
|
|
||||||
sql.append(" (select count(*) from issues where issues.project_id in (" + subSql.toString()
|
|
||||||
+ ") and issues.status_id=16 and issues.assigned_to_id is null) as unassigned_waiting_issue_count, ");
|
|
||||||
sql.append(" (select min(created_on) from issues where issues.project_id in (" + subSql.toString() + ")) as first_issue_create, ");
|
|
||||||
sql.append(" (select max(updated_on) from issues where issues.project_id in (" + subSql.toString() + ")) as last_issue_update ");
|
|
||||||
|
|
||||||
sql.append("FROM ");
|
|
||||||
sql.append(" projects as currentProject ");
|
|
||||||
sql.append("WHERE ");
|
|
||||||
sql.append(" currentProject.status=1 and currentProject.is_public=1;");
|
|
||||||
|
|
||||||
// System.out.println(sql.toStringSeparatedBy("\n"));
|
|
||||||
|
|
||||||
this.connection.setAutoCommit(true);
|
|
||||||
statement = this.connection.prepareStatement(sql.toString());
|
|
||||||
resultSet = statement.executeQuery();
|
|
||||||
|
|
||||||
while (resultSet.next())
|
|
||||||
{
|
|
||||||
long id = resultSet.getLong(1);
|
|
||||||
String identifier = resultSet.getString(2);
|
|
||||||
String name = resultSet.getString(3);
|
|
||||||
Long parentId = SQLUtils.getNullableLong(resultSet, 4);
|
|
||||||
|
|
||||||
Project project = new Project(id, identifier, name, parentId);
|
|
||||||
project.setChildCount(resultSet.getLong(5));
|
|
||||||
project.setLastUpdate(AgirStatoolUtils.toLocaleDateTime(resultSet.getTimestamp(6)));
|
|
||||||
|
|
||||||
project.issueStats().setCount(resultSet.getLong(7));
|
|
||||||
project.issueStats().setNewCount(resultSet.getLong(8));
|
|
||||||
project.issueStats().setOngoingCount(resultSet.getLong(9));
|
|
||||||
project.issueStats().setResolvedCount(resultSet.getLong(10));
|
|
||||||
project.issueStats().setClosedCount(resultSet.getLong(11));
|
|
||||||
project.issueStats().setRejectedCount(resultSet.getLong(12));
|
|
||||||
project.issueStats().setConfirmedCount(resultSet.getLong(13));
|
|
||||||
project.issueStats().setMaybeCount(resultSet.getLong(14));
|
|
||||||
project.issueStats().setWaitingCount(resultSet.getLong(15));
|
|
||||||
|
|
||||||
project.issueStats().setUnassignedCount(resultSet.getLong(16));
|
|
||||||
project.issueStats().setUnassignedNewCount(resultSet.getLong(17));
|
|
||||||
project.issueStats().setUnassignedOngoingCount(resultSet.getLong(18));
|
|
||||||
project.issueStats().setUnassignedResolvedCount(resultSet.getLong(19));
|
|
||||||
project.issueStats().setUnassignedClosedCount(resultSet.getLong(20));
|
|
||||||
project.issueStats().setUnassignedRejectedCount(resultSet.getLong(21));
|
|
||||||
project.issueStats().setUnassignedConfirmedCount(resultSet.getLong(22));
|
|
||||||
project.issueStats().setUnassignedMaybeCount(resultSet.getLong(23));
|
|
||||||
project.issueStats().setUnassignedWaitingCount(resultSet.getLong(24));
|
|
||||||
|
|
||||||
project.issueStats().setFirstCreate(AgirStatoolUtils.toLocaleDateTime(resultSet.getTimestamp(25)));
|
|
||||||
project.issueStats().setLastUpdate(AgirStatoolUtils.toLocaleDateTime(resultSet.getTimestamp(26)));
|
|
||||||
|
|
||||||
result.add(project);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (SQLException exception)
|
|
||||||
{
|
|
||||||
throw new AgirStatoolException("Error reading projects extended: " + exception.getMessage(), exception);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
SQLUtils.closeQuietly(statement, resultSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List projects consolidated.
|
|
||||||
*
|
|
||||||
* @return the projects
|
|
||||||
* @throws AgirStatoolException
|
|
||||||
* the agir statool exception
|
|
||||||
*/
|
|
||||||
public Projects fetchProjectsWithSubStats() throws AgirStatoolException
|
|
||||||
{
|
|
||||||
Projects result;
|
|
||||||
|
|
||||||
result = fetchProjectsWithStats(Project.Type.CONSOLIDATED);
|
|
||||||
|
|
||||||
//
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putTouchFile()
|
public void putTouchFile()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ package org.april.agirstatool.core;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -47,6 +46,162 @@ public class AgirStatoolUtils
|
||||||
public static final DateTimeFormatter PATTERN_SHORTDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy", Locale.FRANCE);
|
public static final DateTimeFormatter PATTERN_SHORTDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy", Locale.FRANCE);
|
||||||
public static final DateTimeFormatter PATTERN_LONGDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy hh':'mm", Locale.FRANCE);
|
public static final DateTimeFormatter PATTERN_LONGDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy hh':'mm", Locale.FRANCE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the week labels.
|
||||||
|
*
|
||||||
|
* @param start
|
||||||
|
* the start
|
||||||
|
* @return the string list
|
||||||
|
*/
|
||||||
|
public static StringList buildWeekLabels(final LocalDate start)
|
||||||
|
{
|
||||||
|
StringList result;
|
||||||
|
|
||||||
|
result = buildWeekLabels(start, LocalDate.now());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the week labels.
|
||||||
|
*
|
||||||
|
* @param start
|
||||||
|
* the start
|
||||||
|
* @param end
|
||||||
|
* the end
|
||||||
|
* @return the string list
|
||||||
|
*/
|
||||||
|
public static StringList buildWeekLabels(final LocalDate start, final LocalDate end)
|
||||||
|
{
|
||||||
|
StringList result;
|
||||||
|
|
||||||
|
result = new StringList();
|
||||||
|
|
||||||
|
if (start != null)
|
||||||
|
{
|
||||||
|
LocalDate normalizedEnd = AgirStatoolUtils.normaliseWeekDate(end);
|
||||||
|
LocalDate date = AgirStatoolUtils.normaliseWeekDate(start);
|
||||||
|
while (date.isBefore(normalizedEnd) || date.isEqual(normalizedEnd))
|
||||||
|
{
|
||||||
|
String label = date.format(DateTimeFormatter.ofPattern("yyyy-MMM", Locale.FRANCE));
|
||||||
|
result.add(label);
|
||||||
|
date = date.plusWeeks(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the week max ages.
|
||||||
|
*
|
||||||
|
* @param project
|
||||||
|
* the project
|
||||||
|
* @param start
|
||||||
|
* the start
|
||||||
|
* @param end
|
||||||
|
* the end
|
||||||
|
* @return the string list
|
||||||
|
*/
|
||||||
|
public static StringList buildWeekMaxAges(final Project project, final LocalDate start, final LocalDate end)
|
||||||
|
{
|
||||||
|
StringList result;
|
||||||
|
|
||||||
|
result = new StringList();
|
||||||
|
|
||||||
|
if (start != null)
|
||||||
|
{
|
||||||
|
LocalDate date = AgirStatoolUtils.normaliseWeekDate(start);
|
||||||
|
LocalDate normalizedEnd = AgirStatoolUtils.normaliseWeekDate(end);
|
||||||
|
while (date.isBefore(normalizedEnd) || date.isEqual(normalizedEnd))
|
||||||
|
{
|
||||||
|
Stat stat = project.issues().extractActivedAt(date).computeStat(date);
|
||||||
|
|
||||||
|
result.add(String.valueOf(stat.getMax()));
|
||||||
|
|
||||||
|
//
|
||||||
|
date = date.plusWeeks(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the week mean ages.
|
||||||
|
*
|
||||||
|
* @param project
|
||||||
|
* the project
|
||||||
|
* @param start
|
||||||
|
* the start
|
||||||
|
* @param end
|
||||||
|
* the end
|
||||||
|
* @return the string list
|
||||||
|
*/
|
||||||
|
public static StringList buildWeekMeanAges(final Project project, final LocalDate start, final LocalDate end)
|
||||||
|
{
|
||||||
|
StringList result;
|
||||||
|
|
||||||
|
result = new StringList();
|
||||||
|
|
||||||
|
if (start != null)
|
||||||
|
{
|
||||||
|
LocalDate date = AgirStatoolUtils.normaliseWeekDate(start);
|
||||||
|
LocalDate normalizedEnd = AgirStatoolUtils.normaliseWeekDate(end);
|
||||||
|
while (date.isBefore(normalizedEnd) || date.isEqual(normalizedEnd))
|
||||||
|
{
|
||||||
|
Stat stat = project.issues().extractActivedAt(date).computeStat(date);
|
||||||
|
|
||||||
|
result.add(String.format(Locale.ENGLISH, "%.2f", stat.getMean()));
|
||||||
|
|
||||||
|
//
|
||||||
|
date = date.plusWeeks(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the week min ages.
|
||||||
|
*
|
||||||
|
* @param project
|
||||||
|
* the project
|
||||||
|
* @param start
|
||||||
|
* the start
|
||||||
|
* @param end
|
||||||
|
* the end
|
||||||
|
* @return the string list
|
||||||
|
*/
|
||||||
|
public static StringList buildWeekMinAges(final Project project, final LocalDate start, final LocalDate end)
|
||||||
|
{
|
||||||
|
StringList result;
|
||||||
|
|
||||||
|
result = new StringList();
|
||||||
|
|
||||||
|
if (start != null)
|
||||||
|
{
|
||||||
|
LocalDate date = AgirStatoolUtils.normaliseWeekDate(start);
|
||||||
|
LocalDate normalizedEnd = AgirStatoolUtils.normaliseWeekDate(end);
|
||||||
|
while (date.isBefore(normalizedEnd) || date.isEqual(normalizedEnd))
|
||||||
|
{
|
||||||
|
Stat stat = project.issues().extractActivedAt(date).computeStat(date);
|
||||||
|
|
||||||
|
result.add(String.valueOf(stat.getMin()));
|
||||||
|
|
||||||
|
//
|
||||||
|
date = date.plusWeeks(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalise week date.
|
* Normalise week date.
|
||||||
*
|
*
|
||||||
|
@ -376,30 +531,6 @@ public class AgirStatoolUtils
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* To date time.
|
|
||||||
*
|
|
||||||
* @param source
|
|
||||||
* the source
|
|
||||||
* @return the local date time
|
|
||||||
*/
|
|
||||||
public static LocalDateTime toLocaleDateTime(final java.sql.Timestamp source)
|
|
||||||
{
|
|
||||||
LocalDateTime result;
|
|
||||||
|
|
||||||
if (source == null)
|
|
||||||
{
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = LocalDateTime.ofEpochSecond(source.getTime() / 1000, 0, ZoneOffset.UTC);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To year week.
|
* To year week.
|
||||||
*
|
*
|
||||||
|
|
166
src/org/april/agirstatool/core/Issue.java
Normal file
166
src/org/april/agirstatool/core/Issue.java
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Christian Pierre MOMON <christian.momon@devinsy.fr>
|
||||||
|
*
|
||||||
|
* This file is part of AgirStatool, simple key value database.
|
||||||
|
*
|
||||||
|
* AgirStatool 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.
|
||||||
|
*
|
||||||
|
* AgirStatool 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with AgirStatool. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.april.agirstatool.core;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Issue.
|
||||||
|
*/
|
||||||
|
public class Issue
|
||||||
|
{
|
||||||
|
private int id;
|
||||||
|
private Integer projectId;
|
||||||
|
private LocalDateTime createdOn;
|
||||||
|
private LocalDateTime closedOn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new issue.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* the id
|
||||||
|
* @param createdOn
|
||||||
|
* the created on
|
||||||
|
*/
|
||||||
|
public Issue(final int id, final Integer projectId, final LocalDateTime createdOn)
|
||||||
|
{
|
||||||
|
this(id, projectId, createdOn, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new issue.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* the id
|
||||||
|
* @param createdOn
|
||||||
|
* the created on
|
||||||
|
* @param closedOn
|
||||||
|
* the closed on
|
||||||
|
*/
|
||||||
|
public Issue(final int id, final Integer projectId, final LocalDateTime createdOn, final LocalDateTime closedOn)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
this.projectId = projectId;
|
||||||
|
this.createdOn = createdOn;
|
||||||
|
this.closedOn = closedOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Age in days.
|
||||||
|
*
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
|
public int getAgeInDays()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
long start = this.createdOn.toEpochSecond(ZoneOffset.UTC);
|
||||||
|
long end;
|
||||||
|
if (this.closedOn == null)
|
||||||
|
{
|
||||||
|
end = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
end = this.closedOn.toEpochSecond(ZoneOffset.UTC);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = (int) ((end - start) / (24 * 60 * 60));
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the age in days.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the age in days
|
||||||
|
*/
|
||||||
|
public int getAgeInDays(final LocalDate date)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (date == null)
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else if ((this.closedOn != null) && (this.closedOn.isBefore(LocalDateTime.of(date, LocalTime.MAX))))
|
||||||
|
{
|
||||||
|
long start = this.createdOn.toEpochSecond(ZoneOffset.UTC);
|
||||||
|
long end = this.closedOn.toEpochSecond(ZoneOffset.UTC);
|
||||||
|
|
||||||
|
result = (int) ((end - start) / (24 * 60 * 60));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long start = this.createdOn.toEpochSecond(ZoneOffset.UTC);
|
||||||
|
long end = LocalDateTime.of(date, LocalTime.MAX).toEpochSecond(ZoneOffset.UTC);
|
||||||
|
|
||||||
|
result = (int) ((end - start) / (24 * 60 * 60));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getClosedOn()
|
||||||
|
{
|
||||||
|
return this.closedOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getCreatedOn()
|
||||||
|
{
|
||||||
|
return this.createdOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId()
|
||||||
|
{
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getProjectId()
|
||||||
|
{
|
||||||
|
return this.projectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClosedOn(final LocalDateTime closedOn)
|
||||||
|
{
|
||||||
|
this.closedOn = closedOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedOn(final LocalDateTime createdOn)
|
||||||
|
{
|
||||||
|
this.createdOn = createdOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final int id)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProjectId(final Integer projectId)
|
||||||
|
{
|
||||||
|
this.projectId = projectId;
|
||||||
|
}
|
||||||
|
}
|
129
src/org/april/agirstatool/core/Issues.java
Normal file
129
src/org/april/agirstatool/core/Issues.java
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Christian Pierre MOMON <christian.momon@devinsy.fr>
|
||||||
|
*
|
||||||
|
* This file is part of AgirStatool, simple key value database.
|
||||||
|
*
|
||||||
|
* AgirStatool 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.
|
||||||
|
*
|
||||||
|
* AgirStatool 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with AgirStatool. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.april.agirstatool.core;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class IssueList.
|
||||||
|
*/
|
||||||
|
public class Issues extends ArrayList<Issue>
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -6241164269103539500L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new issue list.
|
||||||
|
*/
|
||||||
|
public Issues()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new issue list.
|
||||||
|
*
|
||||||
|
* @param capacity
|
||||||
|
* the capacity
|
||||||
|
*/
|
||||||
|
public Issues(final int capacity)
|
||||||
|
{
|
||||||
|
super(capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute stat.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the stat
|
||||||
|
*/
|
||||||
|
public Stat computeStat()
|
||||||
|
{
|
||||||
|
Stat result;
|
||||||
|
|
||||||
|
result = new Stat();
|
||||||
|
for (Issue issue : this)
|
||||||
|
{
|
||||||
|
int age = issue.getAgeInDays();
|
||||||
|
result.addValue(age);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute stat.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the stat
|
||||||
|
*/
|
||||||
|
public Stat computeStat(final LocalDate date)
|
||||||
|
{
|
||||||
|
Stat result;
|
||||||
|
|
||||||
|
result = new Stat();
|
||||||
|
for (Issue issue : this)
|
||||||
|
{
|
||||||
|
int age = issue.getAgeInDays(date);
|
||||||
|
result.addValue(age);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract aticved at.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @return the issue list
|
||||||
|
*/
|
||||||
|
public Issues extractActivedAt(final LocalDate date)
|
||||||
|
{
|
||||||
|
Issues result;
|
||||||
|
|
||||||
|
result = new Issues();
|
||||||
|
|
||||||
|
for (Issue issue : this)
|
||||||
|
{
|
||||||
|
LocalDate createdOn = issue.getCreatedOn().toLocalDate();
|
||||||
|
LocalDate closedOn;
|
||||||
|
if (issue.getClosedOn() == null)
|
||||||
|
{
|
||||||
|
closedOn = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
closedOn = issue.getClosedOn().toLocalDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!createdOn.isAfter(date)) && ((issue.getClosedOn() == null) || (!closedOn.isBefore(date))))
|
||||||
|
{
|
||||||
|
result.add(issue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,7 @@ public class Project
|
||||||
private Projects subProjects;
|
private Projects subProjects;
|
||||||
private IssueStats stats;
|
private IssueStats stats;
|
||||||
private LocalDateTime lastUpdate;
|
private LocalDateTime lastUpdate;
|
||||||
|
private Issues issues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new project.
|
* Instantiates a new project.
|
||||||
|
@ -64,6 +65,7 @@ public class Project
|
||||||
this.subProjects = new Projects();
|
this.subProjects = new Projects();
|
||||||
this.childCount = 0;
|
this.childCount = 0;
|
||||||
this.stats = new IssueStats();
|
this.stats = new IssueStats();
|
||||||
|
this.issues = new Issues();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getChildCount()
|
public long getChildCount()
|
||||||
|
@ -171,6 +173,11 @@ public class Project
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Issues issues()
|
||||||
|
{
|
||||||
|
return this.issues;
|
||||||
|
}
|
||||||
|
|
||||||
public IssueStats issueStats()
|
public IssueStats issueStats()
|
||||||
{
|
{
|
||||||
return this.stats;
|
return this.stats;
|
||||||
|
|
131
src/org/april/agirstatool/core/Stat.java
Normal file
131
src/org/april/agirstatool/core/Stat.java
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Christian Pierre MOMON <christian.momon@devinsy.fr>
|
||||||
|
*
|
||||||
|
* This file is part of AgirStatool, simple key value database.
|
||||||
|
*
|
||||||
|
* AgirStatool 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.
|
||||||
|
*
|
||||||
|
* AgirStatool 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with AgirStatool. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.april.agirstatool.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Stat.
|
||||||
|
*/
|
||||||
|
public class Stat
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
double total;
|
||||||
|
double min;
|
||||||
|
double max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new stat.
|
||||||
|
*/
|
||||||
|
public Stat()
|
||||||
|
{
|
||||||
|
this.count = 0;
|
||||||
|
this.total = 0;
|
||||||
|
this.min = 0;
|
||||||
|
this.max = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the value.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
*/
|
||||||
|
public void addValue(final double value)
|
||||||
|
{
|
||||||
|
if (this.count == 0)
|
||||||
|
{
|
||||||
|
this.total = value;
|
||||||
|
this.min = value;
|
||||||
|
this.max = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
if (value < this.min)
|
||||||
|
{
|
||||||
|
this.min = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
this.total += value;
|
||||||
|
|
||||||
|
//
|
||||||
|
if (value > this.max)
|
||||||
|
{
|
||||||
|
this.max = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount()
|
||||||
|
{
|
||||||
|
return this.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMax()
|
||||||
|
{
|
||||||
|
return this.max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the mean.
|
||||||
|
*
|
||||||
|
* @return the mean
|
||||||
|
*/
|
||||||
|
public double getMean()
|
||||||
|
{
|
||||||
|
double result;
|
||||||
|
|
||||||
|
result = this.total / this.count;
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMin()
|
||||||
|
{
|
||||||
|
return this.min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getTotal()
|
||||||
|
{
|
||||||
|
return this.total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCount(final int count)
|
||||||
|
{
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMax(final double max)
|
||||||
|
{
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMin(final double min)
|
||||||
|
{
|
||||||
|
this.min = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal(final double total)
|
||||||
|
{
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,8 +20,6 @@ package org.april.agirstatool.core.pages;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.april.agirstatool.charts.DateCountList;
|
import org.april.agirstatool.charts.DateCountList;
|
||||||
|
@ -70,7 +68,7 @@ public class CreatedClosedCountChartView
|
||||||
|
|
||||||
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "lineChart"));
|
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "lineChart"));
|
||||||
|
|
||||||
StringList labels = buildWeekLabels(start, end);
|
StringList labels = AgirStatoolUtils.buildWeekLabels(start, end);
|
||||||
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
|
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
|
||||||
|
|
||||||
DateCountList dates = project.issueStats().getWeekCreatedIssueCounts();
|
DateCountList dates = project.issueStats().getWeekCreatedIssueCounts();
|
||||||
|
@ -123,7 +121,7 @@ public class CreatedClosedCountChartView
|
||||||
|
|
||||||
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "lineBar"));
|
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "lineBar"));
|
||||||
|
|
||||||
StringList labels = buildWeekLabels(project.issueStats().getFirstCreate().toLocalDate());
|
StringList labels = AgirStatoolUtils.buildWeekLabels(project.issueStats().getFirstCreate().toLocalDate());
|
||||||
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
|
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
|
||||||
|
|
||||||
StringList values = project.issueStats().getWeekCreatedIssueCounts().toValueList();
|
StringList values = project.issueStats().getWeekCreatedIssueCounts().toValueList();
|
||||||
|
@ -192,54 +190,6 @@ public class CreatedClosedCountChartView
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the week labels.
|
|
||||||
*
|
|
||||||
* @param start
|
|
||||||
* the start
|
|
||||||
* @return the string list
|
|
||||||
*/
|
|
||||||
private static StringList buildWeekLabels(final LocalDate start)
|
|
||||||
{
|
|
||||||
StringList result;
|
|
||||||
|
|
||||||
result = buildWeekLabels(start, LocalDate.now());
|
|
||||||
|
|
||||||
//
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the week labels.
|
|
||||||
*
|
|
||||||
* @param start
|
|
||||||
* the start
|
|
||||||
* @param end
|
|
||||||
* the end
|
|
||||||
* @return the string list
|
|
||||||
*/
|
|
||||||
private static StringList buildWeekLabels(final LocalDate start, final LocalDate end)
|
|
||||||
{
|
|
||||||
StringList result;
|
|
||||||
|
|
||||||
result = new StringList();
|
|
||||||
|
|
||||||
if (start != null)
|
|
||||||
{
|
|
||||||
LocalDate normalizedEnd = AgirStatoolUtils.normaliseWeekDate(end);
|
|
||||||
LocalDate date = AgirStatoolUtils.normaliseWeekDate(start);
|
|
||||||
while (date.isBefore(normalizedEnd) || date.isEqual(normalizedEnd))
|
|
||||||
{
|
|
||||||
String label = date.format(DateTimeFormatter.ofPattern("yyyy-MMM", Locale.FRANCE));
|
|
||||||
result.add(label);
|
|
||||||
date = date.plusWeeks(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the year.
|
* Builds the year.
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,8 +20,6 @@ package org.april.agirstatool.core.pages;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.april.agirstatool.charts.DateCount;
|
import org.april.agirstatool.charts.DateCount;
|
||||||
|
@ -71,7 +69,7 @@ public class CreatedClosedDiffChartView
|
||||||
|
|
||||||
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "line2Chart"));
|
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "line2Chart"));
|
||||||
|
|
||||||
StringList labels = buildWeekLabels(start, end);
|
StringList labels = AgirStatoolUtils.buildWeekLabels(start, end);
|
||||||
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
|
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
|
||||||
|
|
||||||
DateCountList createdDates = project.issueStats().getWeekCreatedIssueCounts();
|
DateCountList createdDates = project.issueStats().getWeekCreatedIssueCounts();
|
||||||
|
@ -177,54 +175,6 @@ public class CreatedClosedDiffChartView
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the week labels.
|
|
||||||
*
|
|
||||||
* @param start
|
|
||||||
* the start
|
|
||||||
* @return the string list
|
|
||||||
*/
|
|
||||||
private static StringList buildWeekLabels(final LocalDate start)
|
|
||||||
{
|
|
||||||
StringList result;
|
|
||||||
|
|
||||||
result = buildWeekLabels(start, LocalDate.now());
|
|
||||||
|
|
||||||
//
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the week labels.
|
|
||||||
*
|
|
||||||
* @param start
|
|
||||||
* the start
|
|
||||||
* @param end
|
|
||||||
* the end
|
|
||||||
* @return the string list
|
|
||||||
*/
|
|
||||||
private static StringList buildWeekLabels(final LocalDate start, final LocalDate end)
|
|
||||||
{
|
|
||||||
StringList result;
|
|
||||||
|
|
||||||
result = new StringList();
|
|
||||||
|
|
||||||
if (start != null)
|
|
||||||
{
|
|
||||||
LocalDate normalizedEnd = AgirStatoolUtils.normaliseWeekDate(end);
|
|
||||||
LocalDate date = AgirStatoolUtils.normaliseWeekDate(start);
|
|
||||||
while (date.isBefore(normalizedEnd) || date.isEqual(normalizedEnd))
|
|
||||||
{
|
|
||||||
String label = date.format(DateTimeFormatter.ofPattern("yyyy-MMM", Locale.FRANCE));
|
|
||||||
result.add(label);
|
|
||||||
date = date.plusWeeks(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the year.
|
* Builds the year.
|
||||||
*
|
*
|
||||||
|
|
198
src/org/april/agirstatool/core/pages/IssueAgeChartView.java
Normal file
198
src/org/april/agirstatool/core/pages/IssueAgeChartView.java
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Christian Pierre MOMON <christian.momon@devinsy.fr>
|
||||||
|
*
|
||||||
|
* This file is part of AgirStatool, simple key value database.
|
||||||
|
*
|
||||||
|
* AgirStatool 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.
|
||||||
|
*
|
||||||
|
* AgirStatool 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with AgirStatool. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.april.agirstatool.core.pages;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.april.agirstatool.core.AgirStatool;
|
||||||
|
import org.april.agirstatool.core.AgirStatoolException;
|
||||||
|
import org.april.agirstatool.core.AgirStatoolUtils;
|
||||||
|
import org.april.agirstatool.core.Project;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import fr.devinsy.strings.StringList;
|
||||||
|
import fr.devinsy.xidyn.utils.XidynUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class projectsRawPageBuilder.
|
||||||
|
*/
|
||||||
|
public class IssueAgeChartView
|
||||||
|
{
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(IssueAgeChartView.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the.
|
||||||
|
*
|
||||||
|
* @param title
|
||||||
|
* the title
|
||||||
|
* @param project
|
||||||
|
* the project
|
||||||
|
* @param start
|
||||||
|
* the start
|
||||||
|
* @param end
|
||||||
|
* the end
|
||||||
|
* @return the string
|
||||||
|
* @throws AgirStatoolException
|
||||||
|
* the agir statool exception
|
||||||
|
*/
|
||||||
|
public static String build(final String title, final Project project, final LocalDate start, final LocalDate end) throws AgirStatoolException
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (project.hasIssue())
|
||||||
|
{
|
||||||
|
String source = XidynUtils.load(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/issueAgeChartView.xhtml"));
|
||||||
|
String code = XidynUtils.extractBodyContent(source);
|
||||||
|
|
||||||
|
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "ageStatsChart"));
|
||||||
|
|
||||||
|
StringList labels = AgirStatoolUtils.buildWeekLabels(start, end);
|
||||||
|
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
|
||||||
|
|
||||||
|
StringList values = AgirStatoolUtils.buildWeekMinAges(project, start, end);
|
||||||
|
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(values));
|
||||||
|
|
||||||
|
values = AgirStatoolUtils.buildWeekMeanAges(project, start, end);
|
||||||
|
code = code.replaceAll("data : \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(values));
|
||||||
|
|
||||||
|
values = AgirStatoolUtils.buildWeekMaxAges(project, start, end);
|
||||||
|
code = code.replaceAll("data : \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(values));
|
||||||
|
|
||||||
|
result = code.toString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = "No issue.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException exception)
|
||||||
|
{
|
||||||
|
throw new AgirStatoolException("Error building ProjectsRaw view: " + exception.getMessage(), exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the full.
|
||||||
|
*
|
||||||
|
* @param title
|
||||||
|
* the title
|
||||||
|
* @param project
|
||||||
|
* the project
|
||||||
|
* @return the string
|
||||||
|
* @throws AgirStatoolException
|
||||||
|
* the agir statool exception
|
||||||
|
*/
|
||||||
|
public static String buildFull(final String title, final Project project) throws AgirStatoolException
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
logger.debug("Building created/concluded chart view…");
|
||||||
|
|
||||||
|
if (project.hasIssue())
|
||||||
|
{
|
||||||
|
result = build(title, project, project.issueStats().getFirstCreate().toLocalDate(), LocalDate.now());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = "No issue.";
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the last months.
|
||||||
|
*
|
||||||
|
* @param title
|
||||||
|
* the title
|
||||||
|
* @param project
|
||||||
|
* the project
|
||||||
|
* @param monthCount
|
||||||
|
* the month count
|
||||||
|
* @return the string
|
||||||
|
* @throws AgirStatoolException
|
||||||
|
* the agir statool exception
|
||||||
|
*/
|
||||||
|
public static String buildLastMonths(final String title, final Project project, final int monthCount) throws AgirStatoolException
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = build(title, project, LocalDate.now().minusMonths(monthCount), LocalDate.now());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the previous year.
|
||||||
|
*
|
||||||
|
* @param title
|
||||||
|
* the title
|
||||||
|
* @param project
|
||||||
|
* the project
|
||||||
|
* @return the string
|
||||||
|
* @throws AgirStatoolException
|
||||||
|
* the agir statool exception
|
||||||
|
*/
|
||||||
|
public static String buildPreviousYear(final String title, final Project project) throws AgirStatoolException
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = buildYear(title, project, LocalDate.now().getYear() - 1);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the year.
|
||||||
|
*
|
||||||
|
* @param title
|
||||||
|
* the title
|
||||||
|
* @param project
|
||||||
|
* the project
|
||||||
|
* @param year
|
||||||
|
* the year
|
||||||
|
* @return the string
|
||||||
|
* @throws AgirStatoolException
|
||||||
|
* the agir statool exception
|
||||||
|
*/
|
||||||
|
public static String buildYear(final String title, final Project project, final int year) throws AgirStatoolException
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
LocalDate start = LocalDate.of(year, 1, 1).minusDays(7);
|
||||||
|
LocalDate end = LocalDate.of(year + 1, 1, 1).minusDays(1);
|
||||||
|
|
||||||
|
result = build(title, project, start, end);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -62,12 +62,16 @@ public class ProjectPage
|
||||||
|
|
||||||
data.setContent("createdClosed3MonthsChart", CreatedClosedCountChartView.buildLastMonths("Created/closed 3 months Count", project, 3));
|
data.setContent("createdClosed3MonthsChart", CreatedClosedCountChartView.buildLastMonths("Created/closed 3 months Count", project, 3));
|
||||||
data.setContent("created-Closed3MonthsChart", CreatedClosedDiffChartView.buildLastMonths("Created-closed 3 months Count", project, 3));
|
data.setContent("created-Closed3MonthsChart", CreatedClosedDiffChartView.buildLastMonths("Created-closed 3 months Count", project, 3));
|
||||||
|
data.setContent("age3MonthsChart", IssueAgeChartView.buildLastMonths("Issue Age 3 months Chart", project, 3));
|
||||||
data.setContent("createdClosed6MonthsChart", CreatedClosedCountChartView.buildLastMonths("Created/closed 6 months Count", project, 6));
|
data.setContent("createdClosed6MonthsChart", CreatedClosedCountChartView.buildLastMonths("Created/closed 6 months Count", project, 6));
|
||||||
data.setContent("created-Closed6MonthsChart", CreatedClosedDiffChartView.buildLastMonths("Created-closed 6 months Count", project, 6));
|
data.setContent("created-Closed6MonthsChart", CreatedClosedDiffChartView.buildLastMonths("Created-closed 6 months Count", project, 6));
|
||||||
|
data.setContent("age6MonthsChart", IssueAgeChartView.buildLastMonths("Issue Age 6 months", project, 6));
|
||||||
data.setContent("createdClosedPreviousYearChart", CreatedClosedCountChartView.buildPreviousYear("Created/closed last year Count", project));
|
data.setContent("createdClosedPreviousYearChart", CreatedClosedCountChartView.buildPreviousYear("Created/closed last year Count", project));
|
||||||
data.setContent("created-ClosedPreviousYearChart", CreatedClosedDiffChartView.buildPreviousYear("Created-closed last year Count", project));
|
data.setContent("created-ClosedPreviousYearChart", CreatedClosedDiffChartView.buildPreviousYear("Created-closed last year Count", project));
|
||||||
|
data.setContent("agePreviousYearChart", IssueAgeChartView.buildPreviousYear("Issue Age Previous Year Chart", project));
|
||||||
data.setContent("createdClosedFullChart", CreatedClosedCountChartView.buildFull("Created/closed Count", project));
|
data.setContent("createdClosedFullChart", CreatedClosedCountChartView.buildFull("Created/closed Count", project));
|
||||||
data.setContent("created-ClosedFullChart", CreatedClosedDiffChartView.buildFull("Created-closed Count", project));
|
data.setContent("created-ClosedFullChart", CreatedClosedDiffChartView.buildFull("Created-closed Count", project));
|
||||||
|
data.setContent("ageFullChart", IssueAgeChartView.buildFull("Issue Age Full Chart", project));
|
||||||
|
|
||||||
data.setContent("issueRawChart", IssueStatChartView.build("Issue Raw Count", project));
|
data.setContent("issueRawChart", IssueStatChartView.build("Issue Raw Count", project));
|
||||||
data.setContent("issueGroupedChart", IssueStatChartView.buildGrouped("Issue Grouped Count", project));
|
data.setContent("issueGroupedChart", IssueStatChartView.buildGrouped("Issue Grouped Count", project));
|
||||||
|
|
92
src/org/april/agirstatool/core/pages/issueAgeChartView.xhtml
Normal file
92
src/org/april/agirstatool/core/pages/issueAgeChartView.xhtml
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>Agir Statool</title>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta content="April" name="keywords" />
|
||||||
|
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="agirstatool.css" />
|
||||||
|
<script src="/commons/sorttable.js" />
|
||||||
|
<script src="Chart.bundle.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="width: 100%; height: 100%; text-align: center; margin: 0 0; border: 1px solid red;">
|
||||||
|
<canvas id="myChart" width="100%" height="100%"></canvas>
|
||||||
|
<script>
|
||||||
|
var ctx = document.getElementById('myChart');
|
||||||
|
var myChart = new Chart(ctx,
|
||||||
|
{
|
||||||
|
type: 'line',
|
||||||
|
data:
|
||||||
|
{
|
||||||
|
labels: ['S01', 'S02', 'S03', 'S04', 'S05'],
|
||||||
|
datasets:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
label: 'min',
|
||||||
|
data: [2, 9, 13, 15, 22, 23],
|
||||||
|
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
||||||
|
borderColor: 'rgba(255, 99, 132, 1)',
|
||||||
|
borderWidth: 1,
|
||||||
|
fill: +1,
|
||||||
|
cubicInterpolationMode: 'monotone',
|
||||||
|
lineTension: 0,
|
||||||
|
pointBorderWidth: 0.00000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'mean',
|
||||||
|
data : [1, 5, 9, 13, 15, 22],
|
||||||
|
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||||
|
borderColor: 'rgba(75, 192, 192, 1)',
|
||||||
|
borderWidth: 1,
|
||||||
|
fill: +2,
|
||||||
|
cubicInterpolationMode: 'monotone',
|
||||||
|
lineTension: 0,
|
||||||
|
pointBorderWidth: 0.00000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'max',
|
||||||
|
data : [1, 5, 9, 13, 15, 22],
|
||||||
|
backgroundColor: 'rgba(153, 102, 255, 0.2)',
|
||||||
|
borderColor: 'rgba(153, 102, 255, 1)',
|
||||||
|
borderWidth: 1,
|
||||||
|
fill: false,
|
||||||
|
cubicInterpolationMode: 'monotone',
|
||||||
|
lineTension: 0,
|
||||||
|
pointBorderWidth: 0.00000001
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options:
|
||||||
|
{
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
title: {
|
||||||
|
display: false,
|
||||||
|
text: 'Min and Max Settings'
|
||||||
|
},
|
||||||
|
scales:
|
||||||
|
{
|
||||||
|
xAxes:
|
||||||
|
[{
|
||||||
|
ticks:
|
||||||
|
{
|
||||||
|
beginAtZero: false
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
yAxes:
|
||||||
|
[{
|
||||||
|
ticks:
|
||||||
|
{
|
||||||
|
beginAtZero: false,
|
||||||
|
suggestedMax: 10,
|
||||||
|
precision: 0
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -27,20 +27,24 @@
|
||||||
<a href="chapril.xhtml" class="button">Chapril</a>
|
<a href="chapril.xhtml" class="button">Chapril</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="3MonthsBox" style="display: none;">
|
<div id="3MonthsBox" style="display: none;">
|
||||||
<div id="createdClosed3MonthsChart" style="display: inline-block; width: 50%; height: 400px;">CREATED/CLOSED 3 MONTHS CHART</div>
|
<div id="createdClosed3MonthsChart" style="display: inline-block; width: 33%; height: 400px;">CREATED/CLOSED 3 MONTHS CHART</div>
|
||||||
<div id="created-Closed3MonthsChart" style="display: inline-block; width: 49%; height: 400px;">CREATED-CLOSED 3 MONTHS CHART</div>
|
<div id="created-Closed3MonthsChart" style="display: inline-block; width: 33%; height: 400px;">CREATED-CLOSED 3 MONTHS CHART</div>
|
||||||
|
<div id="age3MonthsChart" style="display: inline-block; width: 33%; height: 400px;">AGE 3 MONTHS CHART</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="6MonthsBox" style="display: none;">
|
<div id="6MonthsBox" style="display: none;">
|
||||||
<div id="createdClosed6MonthsChart" style="display: inline-block; width: 50%; height: 400px;">CREATED/CLOSED 6 MONTHS CHART</div>
|
<div id="createdClosed6MonthsChart" style="display: inline-block; width: 33%; height: 400px;">CREATED/CLOSED 6 MONTHS CHART</div>
|
||||||
<div id="created-Closed6MonthsChart" style="display: inline-block; width: 49%; height: 400px;">CREATED-CLOSED 6 MONTHS CHART</div>
|
<div id="created-Closed6MonthsChart" style="display: inline-block; width: 33%; height: 400px;">CREATED-CLOSED 6 MONTHS CHART</div>
|
||||||
|
<div id="age6MonthsChart" style="display: inline-block; width: 33%; height: 400px;">AGE 6 MONTHS CHART</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="previousYearBox" style="display: none;">
|
<div id="previousYearBox" style="display: none;">
|
||||||
<div id="createdClosedPreviousYearChart" style="display: inline-block; width: 50%; height: 400px;">CREATED/CLOSED PREVIOUS YEAR CHART</div>
|
<div id="createdClosedPreviousYearChart" style="display: inline-block; width: 33%; height: 400px;">CREATED/CLOSED PREVIOUS YEAR CHART</div>
|
||||||
<div id="created-ClosedPreviousYearChart" style="display: inline-block; width: 49%; height: 400px;">CREATED-CLOSED PREVIOUS YEAR CHART</div>
|
<div id="created-ClosedPreviousYearChart" style="display: inline-block; width: 33%; height: 400px;">CREATED-CLOSED PREVIOUS YEAR CHART</div>
|
||||||
|
<div id="agePreviousYearChart" style="display: inline-block; width: 33%; height: 400px;">AGE PREVIOUS YEAR CHART</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="fullBox">
|
<div id="fullBox">
|
||||||
<div id="createdClosedFullChart" style="height: 400px;" onclick="javascript: selectMainChart('C-C');">CREATED/CLOSED FULL CHART</div>
|
<div id="createdClosedFullChart" style="height: 400px;" onclick="javascript: selectMainChart('C-C');">CREATED/CLOSED FULL CHART</div>
|
||||||
<div id="created-ClosedFullChart" style="height: 400px; display: none;" onclick="javascript: selectMainChart('CC');">CREATED-CLOSED FULL CHART</div>
|
<div id="created-ClosedFullChart" style="height: 400px; display: none;" onclick="javascript: selectMainChart('AGE');">CREATED-CLOSED FULL CHART</div>
|
||||||
|
<div id="ageFullChart" style="display: none; height: 400px;" onclick="javascript: selectMainChart('CC');">ISSUE AGE CHART</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -135,6 +139,7 @@
|
||||||
{
|
{
|
||||||
document.getElementById ('createdClosedFullChart').style.display = 'none';
|
document.getElementById ('createdClosedFullChart').style.display = 'none';
|
||||||
document.getElementById ('created-ClosedFullChart').style.display = 'none';
|
document.getElementById ('created-ClosedFullChart').style.display = 'none';
|
||||||
|
document.getElementById ('ageFullChart').style.display = 'none';
|
||||||
|
|
||||||
if (selection == 'CC')
|
if (selection == 'CC')
|
||||||
{
|
{
|
||||||
|
@ -144,6 +149,10 @@
|
||||||
{
|
{
|
||||||
document.getElementById ('created-ClosedFullChart').style.display = 'block';
|
document.getElementById ('created-ClosedFullChart').style.display = 'block';
|
||||||
}
|
}
|
||||||
|
else if (selection == 'AGE')
|
||||||
|
{
|
||||||
|
document.getElementById ('ageFullChart').style.display = 'block';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in a new issue