Compare commits

...

72 Commits

Author SHA1 Message Date
Christian P. MOMON 62b95f1ccf Build 0.11.4 2021-05-08 22:44:25 +02:00
Christian P. MOMON 43a21307d3 Fixed method name. 2021-05-08 22:42:43 +02:00
Christian P. MOMON 349a378f46 Fixed age week alignment. 2021-05-08 22:42:27 +02:00
Christian P. MOMON c4d466bf54 Build 0.11.3 2021-05-05 04:25:46 +02:00
Christian P. MOMON 10bc11baf4 Added median issue age feature. 2021-05-05 04:25:02 +02:00
Christian P. MOMON 4c28fe2dc7 Build 0.11.2 2021-03-05 01:52:01 +01:00
Christian P. MOMON 292b33d126 Fixed the displayed date of week (plus 6). 2021-03-05 01:50:28 +01:00
Christian P. MOMON a2f50008a5 Build 0.11.1 2021-01-06 17:33:16 +01:00
Christian P. MOMON 79703f2fd7 Removed unuseful lib files. 2021-01-06 17:32:42 +01:00
Christian P. MOMON a057a40b56 Added gDTC direct menu entry. 2021-01-06 17:29:47 +01:00
Christian P. MOMON a68e01bf19 Fixed build.sh for Java 11. 2021-01-02 01:32:37 +01:00
Christian P. MOMON 5c95e5e3ae Build 0.11.0 2021-01-02 01:21:00 +01:00
Christian P. MOMON 419b765c21 Migrated to Java 11. 2021-01-02 01:13:41 +01:00
Christian P. MOMON 9e40534df6 Upgraded devins-strings libs. 2021-01-02 01:10:59 +01:00
Christian P. MOMON 380b368538 Added Year-2 and Year-3 button and graphs. 2021-01-01 12:49:29 +01:00
Christian P. MOMON 5d71a64ead Fixed code. 2020-10-05 02:43:41 +02:00
Christian P. MOMON 37576413f8 Fixed file naming. 2020-08-14 23:21:38 +02:00
Christian P. MOMON 6b046b3c03 Build 0.0.32 2020-03-25 02:52:51 +01:00
Christian P. MOMON 428800b856 Fixed hour format in display. 2020-03-25 02:50:10 +01:00
Christian P. MOMON a1e35e5df9 Build 0.0.31 2020-03-24 02:41:35 +01:00
Christian P. MOMON 924b865624 Added last update date in project page. 2020-03-24 02:40:54 +01:00
Christian P. MOMON 928c902aef Build 0.0.30 2020-03-10 00:36:32 +01:00
Christian P. MOMON afa45130a4 Improved age chart title. 2020-03-08 02:06:43 +01:00
Christian P. MOMON 90ea99494a Build 0.0.29 2020-03-07 04:46:30 +01:00
Christian P. MOMON 73199d704a Fixed version displayed in about page. 2020-03-07 04:46:09 +01:00
Christian P. MOMON c1035161db Build 0.0.28 2020-03-07 04:42:34 +01:00
Christian P. MOMON a7612aae3d Added an about page. 2020-03-07 04:40:56 +01:00
Christian P. MOMON c7d1381d9b Fixed agir all issues link. 2020-03-07 02:20:53 +01:00
Christian P. MOMON 394b8fd17d Build 0.0.27 2020-03-06 14:21:25 +01:00
Christian P. MOMON 81b45bb45d Improved visibility of link to Agir. 2020-03-06 14:17:40 +01:00
Christian P. MOMON d5d189a0be Refactored label for time way. 2020-03-06 14:08:46 +01:00
Christian P. MOMON 0300e19c82 Removed unuseful project name in title. 2020-03-05 03:51:20 +01:00
Christian P. MOMON 8d177e5f35 Formatted code. 2020-03-05 03:50:04 +01:00
Christian P. MOMON 0f58eccab9 Improved README file. 2020-02-26 00:48:49 +01:00
Christian P. MOMON 1a34697d20 Build 0.0.26 2020-02-05 18:54:26 +01:00
Christian P. MOMON 9f6ff3a9cf Fixed damned year alignment. 2020-02-05 18:52:42 +01:00
Christian P. MOMON a444973113 Build 0.0.25 2020-02-05 16:21:59 +01:00
Christian P. MOMON 85287a34cb Fixed closed issue filter. 2020-02-05 16:21:16 +01:00
Christian P. MOMON 986e493706 Build 0.0.24 2020-01-30 23:48:19 +01:00
Christian P. MOMON 0477769261 Fixed labels. 2020-01-30 23:44:27 +01:00
Christian P. MOMON 63cccbe1a7 Build 0.0.23 2020-01-30 23:41:55 +01:00
Christian P. MOMON f2342b8b07 Fixed launcher. Fixed empty parameter call. 2020-01-30 23:41:33 +01:00
Christian P. MOMON 96e9b49939 Build 0.0.22 2020-01-30 23:15:02 +01:00
Christian P. MOMON 8686d746ce Added tooltips on charts. 2020-01-30 23:14:38 +01:00
Christian P. MOMON eafe2083b5 Renamed chart classes. 2020-01-30 22:34:33 +01:00
Christian P. MOMON 2ab42decdf Made Javadoc review. 2020-01-30 19:12:42 +01:00
Christian P. MOMON e3be81e79d Build 0.0.21 2020-01-30 19:09:36 +01:00
Christian P. MOMON cc22463874 Refactored raw/grouped view. 2020-01-30 19:07:22 +01:00
Christian P. MOMON 3a1a1e79d9 Refactored CLI launching. 2020-01-30 16:44:04 +01:00
Christian P. MOMON f6a4d2366b Build 0.0.20 2020-01-30 03:08:24 +01:00
Christian P. MOMON 5060ce34ad Prepared duration issue chart. 2020-01-30 03:07:52 +01:00
Christian P. MOMON 932ab594af Fixed precision Y axes on bar chart. 2020-01-30 02:31:05 +01:00
Christian P. MOMON 3aae196481 Added 12 months views. Improved buttons. 2020-01-30 02:19:52 +01:00
Christian P. MOMON 52c6f6e91e Set 6 months view as default one. 2020-01-30 01:50:48 +01:00
Christian P. MOMON ddbb3d092a Build 0.0.19 2020-01-29 20:28:48 +01:00
Christian P. MOMON 5dffbcb888 Improved age chart. Refactored code. 2020-01-29 20:28:14 +01:00
Christian P. MOMON bc3f4fc26f Fixed age extract issues. 2020-01-29 14:10:50 +01:00
Christian P. MOMON de605e2a55 Added age chart. Refactored code. 2020-01-29 00:51:45 +01:00
Christian P. MOMON b8eecdd60f Improved empty data display. 2020-01-29 00:51:04 +01:00
Christian P. MOMON b28954a344 Build 0.0.18 2020-01-27 17:19:06 +01:00
Christian P. MOMON 0a584053aa Added set main chart on click. 2020-01-27 17:18:10 +01:00
Christian P. MOMON 57c208e242 Fixed locale bug. 2020-01-27 17:01:34 +01:00
Christian P. MOMON d410a7d029 Build 0.0.17 2020-01-27 13:18:41 +01:00
Christian P. MOMON 80818318ab Added full active issue chart. 2020-01-27 13:17:21 +01:00
Christian P. MOMON 357276dcc0 Improved precision on chart axes. 2020-01-25 10:27:24 +01:00
Christian P. MOMON b064fcf652 Build 0.0.16 2020-01-24 13:21:49 +01:00
Christian P. MOMON 2dc325bbca Added display of version. 2020-01-24 13:21:15 +01:00
Christian P. MOMON 5d913617d9 Added active issue chart. Improved Javascript code. 2020-01-24 13:15:31 +01:00
Christian P. MOMON 740bb43cb6 Build 0.0.15 2020-01-23 23:05:29 +01:00
Christian P. MOMON 80bdd05e76 Fixed bad swap of column in unassigned table. Renamed SQL methods. 2020-01-23 23:04:03 +01:00
Christian P. MOMON 3a3952048a Build 0.0.14 2020-01-23 17:58:48 +01:00
Christian P. MOMON 2b22a84103 Add root shortcut button. Add title on down button. 2020-01-23 17:49:28 +01:00
46 changed files with 2870 additions and 1091 deletions

View File

@ -8,18 +8,19 @@
<classpathentry kind="lib" path="lib/Logs/log4j-1.2.17.jar" sourcepath="lib/Logs/log4j-1.2.17-source.zip"/>
<classpathentry kind="lib" path="lib/UnitTesting/hamcrest-core-1.3.jar" sourcepath="lib/UnitTesting/hamcrest-core-1.3-sources.jar"/>
<classpathentry kind="lib" path="lib/hsqldb-2.3.0.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="owner.project.facets" value="java"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/Logs/slf4j-api-1.7.25.jar" sourcepath="lib/Logs/slf4j-api-1.7.25-sources.jar"/>
<classpathentry kind="lib" path="lib/Logs/slf4j-log4j12-1.7.25.jar" sourcepath="lib/Logs/slf4j-log4j12-1.7.25-sources.jar"/>
<classpathentry kind="lib" path="lib/UnitTesting/junit-4.12.jar" sourcepath="lib/UnitTesting/junit-4.12-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-io-2.6.jar" sourcepath="lib/commons-io-2.6-sources.jar"/>
<classpathentry kind="lib" path="lib/commons-lang3-3.7.jar" sourcepath="lib/commons-lang3-3.7-sources.jar"/>
<classpathentry kind="lib" path="lib/devinsy-strings-0.8.2.jar" sourcepath="lib/devinsy-strings-0.8.2-sources.zip"/>
<classpathentry kind="lib" path="lib/devinsy-xml-0.8.2.jar" sourcepath="lib/devinsy-xml-0.8.2-sources.zip"/>
<classpathentry kind="lib" path="lib/xidyn-1.8.2.jar" sourcepath="lib/xidyn-1.8.2-sources.zip"/>
<classpathentry kind="lib" path="lib/commons-cli-1.4.jar" sourcepath="lib/commons-cli-1.4-sources.jar"/>
<classpathentry kind="lib" path="lib/devinsy-strings-0.11.0.jar" sourcepath="lib/devinsy-strings-0.11.0-sources.zip"/>
<classpathentry kind="lib" path="lib/devinsy-xml-0.8.2.jar" sourcepath="lib/devinsy-xml-0.8.2-sources.zip"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="owner.project.facets" value="java"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -1,16 +1,20 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
@ -18,20 +22,23 @@ org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_c
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=49
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0
org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_module_statements=16
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16
org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
@ -121,11 +128,12 @@ org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
@ -156,6 +164,8 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
@ -180,13 +190,17 @@ org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
@ -234,6 +248,8 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do no
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
@ -270,9 +286,12 @@ org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not inser
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
@ -308,9 +327,13 @@ org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_on_off_tags=false
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true
org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true
org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true
org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true
org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true
org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter

View File

@ -3,5 +3,5 @@
<fixed facet="java"/>
<fixed facet="jst.utility"/>
<installed facet="jst.utility" version="1.0"/>
<installed facet="java" version="1.8"/>
<installed facet="java" version="11"/>
</faceted-project>

View File

@ -1,25 +1,26 @@
# Welcome
# AgirStatool
AgirStatool is a simple statistic tool software for Redmine.
# LICENSE
## LICENSE
AgirStatool is released under the GNU AGPL license. Enjoy!
AgirStatool is released under the GNU AGPL+ license. Enjoy!
# AUTHOR
## AUTHOR
Christian Pierre MOMON <christian.momon@devinsy.fr>
# Developer install
## Developer install
TODO
## Unit test environment
### Unit test environment
For unit tests, install the TestNG:
* https://marketplace.eclipse.org/content/testng-eclipse
* Eclipse menu > Help > Eclipse Marketplace > Find "TestNG" > TestNG for Eclipse: Install button
# LOGO
## LOGO
Author: Christian Pierre MOMON <christian.momon@devinsy.fr>
License: Creative Commons CC-BY-SA last version.

View File

@ -1,3 +1,3 @@
#Build Number for ANT. Do not edit!
#Thu Jan 23 17:36:49 CET 2020
build.number=14
#Sat May 08 22:44:18 CEST 2021
build.number=5

View File

@ -1,3 +1,3 @@
product.name=agirstatool
product.revision.major=0
product.revision.minor=0
product.revision.minor=11

View File

@ -41,11 +41,11 @@ function build_snapshot
# Java version check.
javaVersionCheck=`javac -version 2>&1`
if [[ "$javaVersionCheck" =~ ^.*\ 1.8 ]]; then
echo "Java 8 version requirement..... OK"
if [[ "$javaVersionCheck" =~ ^.*\ 11\. ]]; then
echo "Java 11 version requirement..... OK"
let "okCount+=1"
else
echo "Java 8 version requirement..... MISSING"
echo "Java 11 version requirement..... MISSING"
fi
if [ "$okCount" == 3 ]; then
@ -83,11 +83,11 @@ function build_local
# Java version check.
javaVersionCheck=`javac -version 2>&1`
if [[ "$javaVersionCheck" =~ ^.*\ 1.8 ]]; then
echo "Java 8 version requirement..... OK"
if [[ "$javaVersionCheck" =~ ^.*\ 11\. ]]; then
echo "Java 11 version requirement..... OK"
let "okCount+=1"
else
echo "Java 8 version requirement..... MISSING"
echo "Java 11 version requirement..... MISSING"
fi
if [ "$okCount" == 3 ]; then
@ -125,11 +125,11 @@ function build_tagandpush
# Java version check.
javaVersionCheck=`javac -version 2>&1`
if [[ "$javaVersionCheck" =~ ^.*\ 1.8 ]]; then
echo "Java 8 version requirement..... OK"
if [[ "$javaVersionCheck" =~ ^.*\ 11\. ]]; then
echo "Java 11 version requirement..... OK"
let "okCount+=1"
else
echo "Java 8 version requirement..... MISSING"
echo "Java 11 version requirement..... MISSING"
fi
# Git check.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -20,13 +20,11 @@ package org.april.agirstatool;
import java.io.File;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.EnhancedPatternLayout;
import org.apache.log4j.PropertyConfigurator;
import org.april.agirstatool.cli.AgirStatoolCLI;
import org.april.agirstatool.demo.AgirStatool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -63,28 +61,9 @@ public final class AgirStatoolLauncher
else
{
BasicConfigurator.configure(new ConsoleAppender(new EnhancedPatternLayout("%m%n")));
// logger.info("Basic log configuration done.");
// logger.info("Configuration file was not found in [{}].",
// loggerConfig.getAbsoluteFile());
}
// Run.
if (args.length == 0)
{
// TODO
// SikevaGUI.run();
}
else if (ArrayUtils.contains(args, "-demo"))
{
AgirStatool.run(args);
}
else
{
// String[] foo = { "-c",
// "/home/cpm/Projets/AgirStatool/TestZone/agirstatool.conf",
// "listProjects" };
// AgiStatoolCLI.run(foo);
AgirStatoolCLI.run(args);
}
AgirStatoolCLI.run(args);
}
}

View File

@ -39,6 +39,17 @@ public class DateCountList extends ArrayList<DateCount>
super();
}
/**
* Instantiates a new date count list.
*
* @param capacity
* the capacity
*/
public DateCountList(final int capacity)
{
super(capacity);
}
/**
* Indexof.
*

View File

@ -1,225 +0,0 @@
/*
* 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.cli;
import java.io.File;
import java.sql.Connection;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.PropertyConfigurator;
import org.april.agirstatool.core.AgirStatool;
import org.april.agirstatool.core.AgirStatoolException;
import org.april.agirstatool.core.Project;
import org.april.agirstatool.core.Projects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.strings.StringList;
import fr.devinsy.strings.StringsUtils;
import utils.BuildInformation;
/**
* The Class <code>JugaCLI</code> manages a Command Line Interface for Juga.
*
*/
public final class AgirConfig
{
private static Logger logger = LoggerFactory.getLogger(AgirConfig.class);
/**
* Instantiates a new JugaCLI.
*/
private AgirConfig()
{
}
/**
* This method displays the CLI help.
*
*/
public static void help()
{
StringList message = new StringList();
message.append("AgirStatool CLI version ").appendln(BuildInformation.instance().version());
message.appendln("Usage:");
message.appendln(" agirstatool [ -h | -help | --help ]");
message.appendln(" agirstatool -c configurationFilename clear");
message.appendln(" agirstatool -c configurationFilename update");
message.appendln(" agirstatool -c configurationFilename projects");
System.out.println(message.toString());
}
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(final String[] args)
{
// Configure log.
File loggerConfig = new File("log4j.properties");
if (loggerConfig.exists())
{
PropertyConfigurator.configure(loggerConfig.getAbsolutePath());
logger.info("Dedicated log configuration done.");
logger.info("Configuration file was found in [{}].", loggerConfig.getAbsoluteFile());
}
else
{
BasicConfigurator.configure();
logger.info("Basic log configuration done.");
logger.info("Configuration file was not found in [{}].", loggerConfig.getAbsoluteFile());
}
// Run.
AgirConfig.run(args);
}
/**
*
* This method launch CLI.
*
* @param args
* necessary arguments
*/
public static void run(final String[] args)
{
try
{
// Set default catch.
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
@Override
public void uncaughtException(final Thread thread, final Throwable exception)
{
String message;
if (exception instanceof OutOfMemoryError)
{
message = "Java ran out of memory!\n\n";
}
else
{
message = String.format("An error occured: %1s(%2s)", exception.getClass(), exception.getMessage());
}
logger.error("uncaughtException ", exception);
logger.error(message);
logger.info("Oups, an unexpected error occured. Please try again.");
}
});
// logger.info("Single connection opened with [{}].", this.url);
System.out.println("ok");
// This part implements an automate.
int parameterCount = args.length;
switch (parameterCount)
{
case 0:
{
help();
}
break;
case 1:
{
String token = args[0];
if (StringsUtils.containsAny(token, "-h", "-help", "--help"))
{
help();
}
else
{
throw new AgirStatoolException("Bad usage.");
}
}
break;
case 3:
{
String token = args[0];
String configurationFilename = args[1];
String command = args[2];
if ((StringUtils.equals(token, "-c")) && (StringsUtils.containsAny(command, "clear", "update", "projects")))
{
File configurationFile = new File(configurationFilename);
if (!configurationFile.exists())
{
throw new AgirStatoolException("Configuration file does not exist.");
}
else if (!configurationFile.isFile())
{
throw new AgirStatoolException("Configuration file is not a file.");
}
else
{
switch (command)
{
case "clear":
break;
case "update":
break;
case "projects":
{
Connection connection = SQLUtils.getConnexion("jdbc:mysql://localhost/", "agir2020", "admin", "suko7Gun");
AgirStatool statool = new AgirStatool(connection, new File("/home/cpm/Projets/AgirStatool/TestZone/www/"));
Projects projects = statool.listProjects();
String header = String.format("%3s %-30s %-30s %s", "ID", "Identifier", "Name", "ParentId");
System.out.println(header);
for (Project project : projects)
{
String line = String.format("%3d %-30s %-30s %4d", project.getId(), project.getIdentifier(), project.getName(), project.getParentId());
System.out.println(line);
}
}
break;
}
}
}
else
{
System.out.println("Bad usage detected.");
help();
}
}
break;
default:
{
throw new AgirStatoolException("Bad parameter count.");
}
}
}
catch (AgirStatoolException exception)
{
System.err.println("AgirStatoolException = " + exception.getMessage());
logger.error(exception.getMessage(), exception);
help();
}
}
}

View File

@ -22,8 +22,6 @@ import java.io.File;
import java.sql.Connection;
import java.time.LocalDateTime;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.PropertyConfigurator;
import org.april.agirstatool.core.AgirStatool;
import org.april.agirstatool.core.AgirStatoolException;
@ -31,7 +29,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.strings.StringList;
import fr.devinsy.strings.StringsUtils;
import utils.BuildInformation;
/**
@ -50,49 +47,90 @@ public final class AgirStatoolCLI
}
/**
* This method displays the CLI help.
*
* Display help.
*/
public static void help()
public static void displayHelp()
{
StringList message = new StringList();
message.append("AgirStatool CLI version ").appendln(BuildInformation.instance().version());
message.appendln("Usage:");
message.appendln(" agirstatool [ -h | -help | --help ]");
message.appendln(" agirstatool -c configurationFilename clear");
message.appendln(" agirstatool -c configurationFilename update");
message.appendln(" agirstatool -c configurationFilename projects");
message.appendln(" agirstatool -c configurationFilename [ clear | projects | projects+ | update | forceupdate ]");
message.appendln(" agirstatool [ -v | -version | --version ]");
System.out.println(message.toString());
logger.info(message.toString());
}
/**
* The main method.
*
* @param args
* the arguments
* Display version.
*/
public static void main(final String[] args)
public static void displayVersion()
{
// Configure log.
File loggerConfig = new File("log4j.properties");
if (loggerConfig.exists())
StringList message = new StringList();
message.appendln(BuildInformation.instance().version());
logger.info(message.toString());
}
/**
* Checks if is matching.
*
* @param args
* the args
* @param regexps
* the regexps
* @return true, if is matching
*/
public static boolean isMatching(final String[] args, final String... regexps)
{
boolean result;
if ((args.length == 0) && (regexps == null))
{
PropertyConfigurator.configure(loggerConfig.getAbsolutePath());
logger.info("Dedicated log configuration done.");
logger.info("Configuration file was found in [{}].", loggerConfig.getAbsoluteFile());
result = true;
}
else if ((args.length != 0) && (regexps == null))
{
result = false;
}
else if (args.length != regexps.length)
{
result = false;
}
else
{
BasicConfigurator.configure();
// logger.info("Basic log configuration done.");
// logger.info("Configuration file was not found in [{}].",
// loggerConfig.getAbsoluteFile());
boolean ended = false;
int index = 0;
result = false;
while (!ended)
{
if (index < args.length)
{
String arg = args[index];
String regexp = regexps[index];
if (arg.matches(regexp))
{
index += 1;
}
else
{
ended = true;
result = false;
}
}
else
{
ended = true;
result = true;
}
}
}
// Run.
AgirStatoolCLI.run(args);
//
return result;
}
/**
@ -130,120 +168,102 @@ public final class AgirStatoolCLI
logger.info("{} AgirStatool call: {}", LocalDateTime.now(), new StringList(args).toStringSeparatedBy(" "));
// logger.info("Single connection opened with [{}].", this.url);
// This part implements an automate.
int parameterCount = args.length;
switch (parameterCount)
if (isMatching(args))
{
case 0:
logger.info("No parameter.");
displayHelp();
}
else if (isMatching(args, "(-h|--h|--help)"))
{
displayHelp();
}
else if (isMatching(args, "(-v|-version|--version)"))
{
displayVersion();
}
else if (isMatching(args, "-c", ".+", "(clear|projects|projects\\+|update|forceupdate)"))
{
File configurationFile = new File(args[1]);
String action = args[2];
File log4jfile = new File(configurationFile.getParentFile(), "log4j.properties");
if (log4jfile.exists())
{
help();
logger.info("Applying configuration file found in [{}].", log4jfile.getAbsoluteFile());
PropertyConfigurator.configure(log4jfile.getAbsolutePath());
logger.info("Configuration log configuration done.");
}
break;
case 1:
switch (action)
{
String token = args[0];
if (StringsUtils.containsAny(token, "-h", "-help", "--help"))
case "clear":
{
help();
logger.info("Applying clear command…");
AgirStatoolConfigFile config = new AgirStatoolConfigFile(configurationFile);
Connection connection = SQLUtils.getConnexion(config.getDabataseUrl(), config.getDabataseName(), config.getDabataseLogin(), config.getDabatasePassword());
AgirStatool statool = new AgirStatool(connection, new File(config.getTargetDirectory()));
statool.doClearAllPages();
}
else
break;
case "forceupdate":
{
throw new AgirStatoolException("Bad usage.");
logger.info("Applying forceupdate command…");
AgirStatoolConfigFile config = new AgirStatoolConfigFile(configurationFile);
Connection connection = SQLUtils.getConnexion(config.getDabataseUrl(), config.getDabataseName(), config.getDabataseLogin(), config.getDabatasePassword());
AgirStatool statool = new AgirStatool(connection, new File(config.getTargetDirectory()));
statool.doClearAllPages();
statool.doUpdatePages();
}
}
break;
break;
case 3:
{
String token = args[0];
String configurationFilename = args[1];
String command = args[2];
if ((StringUtils.equals(token, "-c")) && (StringsUtils.containsAny(command, "clear", "refresh", "update", "projects", "projects+")))
case "projects":
{
File configurationFile = new File(configurationFilename);
if (!configurationFile.exists())
{
throw new AgirStatoolException("Configuration file does not exist.");
}
else if (!configurationFile.isFile())
{
throw new AgirStatoolException("Configuration file is not a file.");
}
else
{
// Apply -c parameter.
File log4jfile = new File(configurationFile.getParentFile(), "log4j.properties");
if (log4jfile.exists())
{
logger.info("Applying configuration file found in [{}].", log4jfile.getAbsoluteFile());
PropertyConfigurator.configure(log4jfile.getAbsolutePath());
logger.info("Configuration log configuration done.");
}
switch (command)
{
case "clear":
break;
case "refresh":
case "update":
{
logger.info("Update command…");
AgirStatoolConfigFile config = new AgirStatoolConfigFile(configurationFile);
Connection connection = SQLUtils.getConnexion(config.getDabataseUrl(), config.getDabataseName(), config.getDabataseLogin(), config.getDabatasePassword());
AgirStatool statool = new AgirStatool(connection, new File(config.getTargetDirectory()));
statool.doRefreshPages();
}
break;
case "projects":
{
logger.info("projects command…");
AgirStatoolConfigFile config = new AgirStatoolConfigFile(configurationFile);
Connection connection = SQLUtils.getConnexion(config.getDabataseUrl(), config.getDabataseName(), config.getDabataseLogin(), config.getDabatasePassword());
AgirStatool statool = new AgirStatool(connection, new File(config.getTargetDirectory()));
StringList lines = statool.doBuildTextProjectList();
System.out.println(lines);
}
break;
case "projects+":
{
logger.info("projects+ command…");
AgirStatoolConfigFile config = new AgirStatoolConfigFile(configurationFile);
Connection connection = SQLUtils.getConnexion(config.getDabataseUrl(), config.getDabataseName(), config.getDabataseLogin(), config.getDabatasePassword());
AgirStatool statool = new AgirStatool(connection, new File(config.getTargetDirectory()));
StringList lines = statool.doBuildTextProjectExtendedList();
System.out.println(lines);
}
break;
}
}
logger.info("Applying projects command…");
AgirStatoolConfigFile config = new AgirStatoolConfigFile(configurationFile);
Connection connection = SQLUtils.getConnexion(config.getDabataseUrl(), config.getDabataseName(), config.getDabataseLogin(), config.getDabatasePassword());
AgirStatool statool = new AgirStatool(connection, new File(config.getTargetDirectory()));
StringList lines = statool.doBuildTextProjectList();
System.out.println(lines);
}
else
break;
case "projects+":
{
System.out.println("Bad usage detected.");
help();
logger.info("Applying projects+ command…");
AgirStatoolConfigFile config = new AgirStatoolConfigFile(configurationFile);
Connection connection = SQLUtils.getConnexion(config.getDabataseUrl(), config.getDabataseName(), config.getDabataseLogin(), config.getDabatasePassword());
AgirStatool statool = new AgirStatool(connection, new File(config.getTargetDirectory()));
StringList lines = statool.doBuildTextProjectExtendedList();
System.out.println(lines);
}
}
break;
break;
default:
{
throw new AgirStatoolException("Bad parameter count.");
case "update":
{
logger.info("Applying update command…");
AgirStatoolConfigFile config = new AgirStatoolConfigFile(configurationFile);
Connection connection = SQLUtils.getConnexion(config.getDabataseUrl(), config.getDabataseName(), config.getDabataseLogin(), config.getDabatasePassword());
AgirStatool statool = new AgirStatool(connection, new File(config.getTargetDirectory()));
statool.doUpdatePages();
}
break;
}
}
else
{
logger.info("Bad usage.");
displayHelp();
}
//
logger.info("Finished.");
}
catch (AgirStatoolException exception)
{
System.err.println("AgirStatoolException = " + exception.getMessage());
logger.error(exception.getMessage(), exception);
help();
displayHelp();
}
}
}

View File

@ -19,7 +19,6 @@
package org.april.agirstatool.cli;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
@ -39,32 +38,37 @@ public class AgirStatoolConfigFile extends Properties
private static final Logger logger = LoggerFactory.getLogger(AgirStatoolConfigFile.class);
private static final String TIME_PATTERN = "^\\d\\dh\\d\\d$";
/**
* Instantiates a new agir statool config file.
*
* @param source
* the source
* @param configurationFile
* the configuration file
* @throws AgirStatoolException
* the agir statool exception
*/
public AgirStatoolConfigFile(final File source) throws AgirStatoolException
public AgirStatoolConfigFile(final File configurationFile) throws AgirStatoolException
{
super();
try
{
Properties config = loadProperties(source);
for (String key : config.stringPropertyNames())
if (configurationFile == null)
{
put(key, config.getProperty(key));
throw new AgirStatoolException("Configuration file undefined.");
}
else if (!configurationFile.exists())
{
throw new AgirStatoolException("Configuration file does not exist.");
}
else if (!configurationFile.isFile())
{
throw new AgirStatoolException("Configuration file is not a file.");
}
else
{
Properties config = loadProperties(configurationFile);
this.putAll(config);
}
}
catch (FileNotFoundException exception)
{
throw new AgirStatoolException("File not found.", exception);
}
catch (IOException exception)
{

View File

@ -24,6 +24,8 @@ import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import org.apache.commons.lang3.StringUtils;
import org.april.agirstatool.core.AgirStatoolException;
@ -241,4 +243,30 @@ public final class SQLUtils
//
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;
}
}

View File

@ -19,6 +19,7 @@
package org.april.agirstatool.core;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
@ -29,6 +30,7 @@ import java.time.LocalDateTime;
import java.time.ZoneOffset;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.april.agirstatool.charts.DateCount;
import org.april.agirstatool.charts.DateCountList;
import org.april.agirstatool.charts.DateCountMap;
@ -99,7 +101,7 @@ public class AgirStatool
result = new StringList();
Projects projects = listProjectsWithoutSubStats().sortByName();
Projects projects = fetchProjectsWithoutSubStats().sortByName();
String header = String.format("%3s %-30s %-30s %s %s %6s %6s %7s %7s %7s %7s %9s %7s %7s",
"ID",
"Identifier",
@ -181,8 +183,8 @@ public class AgirStatool
{
try
{
// TODO: add filter on .xhtml and .css file.
for (File file : this.targetDirectory.listFiles())
FileFilter filter = new WildcardFileFilter(new String[] { "*.xhtml", "*.html", "*.css", "*.js" });
for (File file : this.targetDirectory.listFiles(filter))
{
FileUtils.forceDelete(file);
}
@ -194,12 +196,12 @@ public class AgirStatool
}
/**
* Do refresh pages.
* Do update pages.
*
* @throws AgirStatoolException
* the agir statool exception
*/
public void doRefreshPages() throws AgirStatoolException
public void doUpdatePages() throws AgirStatoolException
{
try
{
@ -209,35 +211,288 @@ public class AgirStatool
FileUtils.copyURLToFile(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/index.html"), new File(this.targetDirectory, "index.html"));
FileUtils.copyURLToFile(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/agirstatool.css"), new File(this.targetDirectory, "agirstatool.css"));
FileUtils.copyURLToFile(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/Chart.bundle.min.js"), new File(this.targetDirectory, "Chart.bundle.min.js"));
FileUtils.copyURLToFile(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/about.xhtml"), new File(this.targetDirectory, "about.xhtml"));
}
//
Project root = listProjectsAsTree();
// Create welcome page.
refreshPage(root);
updatePage(root);
FileUtils.copyFile(new File(this.targetDirectory, "all.xhtml"), new File(this.targetDirectory, "index.xhtml"));
// Create one page per project.
for (Project project : root.subProjects())
{
refreshPage(project);
updatePage(project);
for (Project subProject : project.subProjects())
{
refreshPage(subProject);
// if (project.getName().equals("Chapril"))
// {
// System.exit(0);
// }
updatePage(subProject);
}
}
}
catch (IOException exception)
{
throw new AgirStatoolException("Error refreshing all: " + exception.getMessage(), exception);
throw new AgirStatoolException("Error updating all: " + exception.getMessage(), exception);
}
}
/**
* Fetch issue open closed dates.
*
* @param project
* the project
* @return the date count map
* @throws AgirStatoolException
* the agir statool exception
*/
public Issues fetchIssues(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())
{
long id = resultSet.getInt(1);
long 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.
*
@ -247,7 +502,7 @@ public class AgirStatool
* @throws AgirStatoolException
* the agir statool exception
*/
public DateCountMap fetchWeekConcludedCount(final Project project) throws AgirStatoolException
public DateCountMap fetchWeekClosedOnCount(final Project project) throws AgirStatoolException
{
DateCountMap result;
@ -290,7 +545,9 @@ public class AgirStatool
sql.append("FROM ");
sql.append(" issues ");
sql.append("WHERE ");
sql.append(" project_id in (" + subSql.toString() + ") and closed_on is not null ");
// sql.append(" project_id in (" + subSql.toString() + ") and
// closed_on is not null and status_id <> 16 ");
sql.append(" project_id in (" + subSql.toString() + ") and status_id in (3, 5, 6) ");
sql.append("GROUP BY ");
sql.append(" date;");
@ -458,7 +715,7 @@ public class AgirStatool
result = new Project(id, identifier, name, parentId);
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().setNewCount(resultSet.getLong(8));
result.issueStats().setOngoingCount(resultSet.getLong(9));
@ -468,8 +725,8 @@ public class AgirStatool
result.issueStats().setConfirmedCount(resultSet.getLong(13));
result.issueStats().setMaybeCount(resultSet.getLong(14));
result.issueStats().setWaitingCount(resultSet.getLong(15));
result.issueStats().setFirstCreate(AgirStatoolUtils.toLocaleDateTime(resultSet.getTimestamp(16)));
result.issueStats().setLastUpdate(AgirStatoolUtils.toLocaleDateTime(resultSet.getTimestamp(17)));
result.issueStats().setFirstCreate(SQLUtils.toLocalDateTime(resultSet.getTimestamp(16)));
result.issueStats().setLastUpdate(SQLUtils.toLocalDateTime(resultSet.getTimestamp(17)));
}
}
catch (SQLException exception)
@ -486,13 +743,13 @@ public class AgirStatool
}
/**
* Checks for to refresh.
* Checks for to update.
*
* @param project
* the project
* @return true, if successful
*/
public boolean hasToRefresh(final Project project)
public boolean hasToUpdate(final Project project)
{
boolean result;
@ -587,7 +844,7 @@ public class AgirStatool
Project project = new Project(id, identifier, name, parentId);
project.setChildCount(resultSet.getLong(5));
project.setLastUpdate(AgirStatoolUtils.toLocaleDateTime(resultSet.getTimestamp(6)));
project.setLastUpdate(SQLUtils.toLocalDateTime(resultSet.getTimestamp(6)));
result.add(project);
}
@ -621,10 +878,10 @@ public class AgirStatool
result = getRootProject();
//
Projects projects = listProjectsWithSubStats();
Projects projects = fetchProjectsWithSubStats();
// Add parent projects with alone statistics.
for (Project project : listProjectsWithoutSubStats())
for (Project project : fetchProjectsWithoutSubStats())
{
if (project.hasChild())
{
@ -638,13 +895,17 @@ public class AgirStatool
// Fill created and concluded issues history.
{
{
Issues issues = fetchIssues(result);
result.issues().addAll(issues);
}
{
DateCountMap map = fetchWeekCreatedCount(result);
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, result.issueStats().getFirstCreate().toLocalDate());
result.issueStats().setWeekCreatedIssueCounts(counts);
}
{
DateCountMap map = fetchWeekConcludedCount(result);
DateCountMap map = fetchWeekClosedOnCount(result);
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, result.issueStats().getFirstCreate().toLocalDate());
result.issueStats().setWeekConcludedIssueCounts(counts);
}
@ -654,13 +915,17 @@ public class AgirStatool
logger.debug("Fetching Created/Closed history for " + project.getName());
if (project.hasIssue())
{
{
Issues issues = fetchIssues(project);
project.issues().addAll(issues);
}
{
DateCountMap map = fetchWeekCreatedCount(project);
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, project.issueStats().getFirstCreate().toLocalDate());
project.issueStats().setWeekCreatedIssueCounts(counts);
}
{
DateCountMap map = fetchWeekConcludedCount(project);
DateCountMap map = fetchWeekClosedOnCount(project);
DateCountList counts = AgirStatoolUtils.normalizedWeekCountList(map, project.issueStats().getFirstCreate().toLocalDate());
project.issueStats().setWeekConcludedIssueCounts(counts);
}
@ -688,221 +953,27 @@ public class AgirStatool
}
/**
* List projects extended.
*
* @return the projects
* @throws AgirStatoolException
* the agir statool exception
*/
public Projects listProjectsWithoutSubStats() throws AgirStatoolException
{
Projects result;
result = listProjectsWithStats(Project.Type.ALONE);
//
return result;
}
/**
* List projects with stats.
*
* @param type
* the type
* @return the projects
* @throws AgirStatoolException
* the agir statool exception
*/
public Projects listProjectsWithStats(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 listProjectsWithSubStats() throws AgirStatoolException
{
Projects result;
result = listProjectsWithStats(Project.Type.CONSOLIDATED);
//
return result;
}
public void putTouchFile()
{
}
/**
* Refresh.
*
* @param projectId
* the project id
* @throws AgirStatoolException
* the agir statool exception
*/
public void refresh(final String projectId) throws AgirStatoolException
{
}
/**
* Update.
*/
public void refreshChangedProjects()
{
}
/**
* Refresh page.
* Update page.
*
* @param project
* the project
* @throws AgirStatoolException
* the agir statool exception
*/
public void refreshPage(final Project project) throws AgirStatoolException
public void updatePage(final Project project) throws AgirStatoolException
{
try
{
if (hasToRefresh(project))
if (hasToUpdate(project))
{
logger.info("Refresh project page for {}", project.getName());
logger.info("Update project page for {}", project.getName());
String page = ProjectPage.build(project);
FileUtils.write(new File(this.targetDirectory, project.getIdentifier() + ".xhtml"), page, StandardCharsets.UTF_8);
}
}
catch (IOException exception)
{
throw new AgirStatoolException("Error refreshing page: " + exception.getMessage(), exception);
throw new AgirStatoolException("Error updating page: " + exception.getMessage(), exception);
}
}
}

View File

@ -20,16 +20,16 @@ package org.april.agirstatool.core;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.april.agirstatool.charts.DateCount;
import org.april.agirstatool.charts.DateCountList;
import org.april.agirstatool.charts.DateCountMap;
import org.april.agirstatool.core.pages.ProjectPage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -41,10 +41,234 @@ import fr.devinsy.strings.StringsUtils;
*/
public class AgirStatoolUtils
{
private static Logger logger = LoggerFactory.getLogger(ProjectPage.class);
private static Logger logger = LoggerFactory.getLogger(AgirStatoolUtils.class);
public static final DateTimeFormatter PATTERN_SHORTDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy");
public static final DateTimeFormatter PATTERN_LONGDATE = DateTimeFormatter.ofPattern("dd/MM/yyyy hh'h'mm");
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 StringList buildWeekDuration(final Project project, final LocalDate start, final LocalDate end)
{
StringList result;
result = new StringList();
if (start != null)
{
Issues issues = new Issues();
issues.addAll(project.issues());
issues.sort(IssueComparator.Sorting.CLOSEDON);
LocalDate date = AgirStatoolUtils.normaliseWeekDate(start);
LocalDate normalizedEnd = AgirStatoolUtils.normaliseWeekDate(end);
while (!date.isAfter(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 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))
{
// The normalized date is set to the first day of the week.
// The displayed date is set to the last day of the week. So
// plus 6.
String label = date.plusDays(6).format(DateTimeFormatter.ISO_DATE);
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 = normaliseWeekDate(start).plusDays(6);
LocalDate normalizedEnd = normaliseWeekDate(end).plusDays(6);
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 = normaliseWeekDate(start).plusDays(6);
LocalDate normalizedEnd = normaliseWeekDate(end).plusDays(6);
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 median ages.
*
* @param project
* the project
* @param start
* the start
* @param end
* the end
* @return the string list
*/
public static StringList buildWeekMedianAges(final Project project, final LocalDate start, final LocalDate end)
{
StringList result;
result = new StringList();
if (start != null)
{
LocalDate date = normaliseWeekDate(start).plusDays(6);
LocalDate normalizedEnd = normaliseWeekDate(end).plusDays(6);
while (date.isBefore(normalizedEnd) || date.isEqual(normalizedEnd))
{
double stat = project.issues().extractActivedAt(date).computeMedian(date);
result.add(String.valueOf(stat));
//
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 = normaliseWeekDate(start).plusDays(6);
LocalDate normalizedEnd = normaliseWeekDate(end).plusDays(6);
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.
@ -89,14 +313,14 @@ public class AgirStatoolUtils
LocalDate normalizedEnd = normaliseWeekDate(end);
LocalDate date = normaliseWeekDate(start);
int index = source.indexOf(start.format(DateTimeFormatter.ofPattern("yyyyww")));
int index = source.indexOf(toYearWeek(start));
if (index == -1)
{
index = 0;
}
while (date.isBefore(normalizedEnd) || date.isEqual(normalizedEnd))
{
String dateToken = date.format(DateTimeFormatter.ofPattern("yyyyww"));
String dateToken = toYearWeek(date);
long count;
if (index < source.size())
{
@ -145,7 +369,7 @@ public class AgirStatoolUtils
long count = 0;
while (date.isBefore(end) || date.isEqual(end))
{
String dateToken = date.format(DateTimeFormatter.ofPattern("yyyyww"));
String dateToken = toYearWeek(date);
DateCount current = source.get(dateToken);
if (current != null)
{
@ -345,6 +569,38 @@ public class AgirStatoolUtils
return result;
}
/**
* To J son numbers.
*
* @param labels
* the labels
* @param values
* the source
* @return the string
*/
public static String toJSonNumbers(final StringList labels, final StringList values)
{
String result;
Iterator<String> labelIterator = labels.iterator();
Iterator<String> valueIterator = values.iterator();
StringList buffer = new StringList();
while (labelIterator.hasNext())
{
String label = labelIterator.next();
String value = valueIterator.next();
// buffer.append("{t: new Date('" + label + "'), y: " + value +
// "}");
buffer.append("{t: '" + label + "', y: " + value + "}");
}
result = StringsUtils.toString(buffer, "[", ",", "]");
//
return result;
}
/**
* To Json strings.
*
@ -376,15 +632,15 @@ public class AgirStatoolUtils
}
/**
* To date time.
* To year week.
*
* @param source
* the source
* @return the local date time
* @return the string
*/
public static LocalDateTime toLocaleDateTime(final java.sql.Timestamp source)
public static String toYearWeek(final LocalDate source)
{
LocalDateTime result;
String result;
if (source == null)
{
@ -392,7 +648,7 @@ public class AgirStatoolUtils
}
else
{
result = LocalDateTime.ofEpochSecond(source.getTime() / 1000, 0, ZoneOffset.UTC);
result = source.format(DateTimeFormatter.ofPattern("YYYYww", Locale.FRANCE));
}
//

View File

@ -1,5 +1,7 @@
package org.april.agirstatool.core;
import java.time.LocalDateTime;
import org.apache.commons.lang3.StringUtils;
/**
@ -109,6 +111,40 @@ public class CompareUtils
return result;
}
/**
* Compare.
*
* @param alpha
* the alpha
* @param bravo
* the bravo
* @return the int
*/
public static int compare(final LocalDateTime alpha, final LocalDateTime bravo)
{
int result;
if ((alpha == null) && (bravo == null))
{
result = 0;
}
else if (alpha == null)
{
result = -1;
}
else if (bravo == null)
{
result = +1;
}
else
{
result = alpha.compareTo(bravo);
}
//
return result;
}
/**
* Compare.
*

View File

@ -0,0 +1,249 @@
/*
* 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 long id;
private Long projectId;
private LocalDateTime createdOn;
private LocalDateTime closedOn;
/**
* Instantiates a new issue.
*
* @param id
* the id
* @param projectId
* the project id
* @param createdOn
* the created on
*/
public Issue(final long id, final Long projectId, final LocalDateTime createdOn)
{
this(id, projectId, createdOn, null);
}
/**
* Instantiates a new issue.
*
* @param id
* the id
* @param projectId
* the project id
* @param createdOn
* the created on
* @param closedOn
* the closed on
*/
public Issue(final long id, final Long 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 long getId()
{
return this.id;
}
public Long getProjectId()
{
return this.projectId;
}
/**
* Checks if is active at.
*
* @param date
* the date
* @return true, if is active at
*/
public boolean isActiveAt(final LocalDate date)
{
boolean result;
LocalDate createdDate = this.createdOn.toLocalDate();
LocalDate closedDate;
if (this.closedOn == null)
{
closedDate = null;
}
else
{
closedDate = this.closedOn.toLocalDate();
}
if ((!createdDate.isAfter(date)) && ((closedDate == null) || (date.isBefore(closedDate))))
{
result = true;
}
else
{
result = false;
}
//
return result;
}
/**
* Checks if is active between.
*
* @param start
* the start
* @param end
* the end
* @return true, if is active between
*/
public boolean isActiveBetween(final LocalDate start, final LocalDate end)
{
boolean result;
if ((start == null) || (end == null))
{
result = false;
}
else
{
LocalDate createdDate = this.createdOn.toLocalDate();
LocalDate closedDate;
if (this.closedOn == null)
{
closedDate = null;
}
else
{
closedDate = this.closedOn.toLocalDate();
}
if ((!createdDate.isAfter(start)) && ((closedDate == null) || (end.isBefore(closedDate))))
{
result = true;
}
else
{
result = false;
}
}
//
return result;
}
public void setClosedOn(final LocalDateTime closedOn)
{
this.closedOn = closedOn;
}
public void setCreatedOn(final LocalDateTime createdOn)
{
this.createdOn = createdOn;
}
public void setId(final long id)
{
this.id = id;
}
public void setProjectId(final Long projectId)
{
this.projectId = projectId;
}
}

View File

@ -0,0 +1,188 @@
package org.april.agirstatool.core;
import java.time.LocalDateTime;
import java.util.Comparator;
/**
* The Class ProjectComparator.
*/
public class IssueComparator implements Comparator<Issue>
{
public enum Sorting
{
ID,
PROJECTID,
CREATEDON,
CLOSEDON
}
private Sorting sorting;
/**
* Instantiates a new project comparator.
*
* @param sorting
* the sorting
*/
public IssueComparator(final Sorting sorting)
{
//
this.sorting = sorting;
}
/**
*
*/
@Override
public int compare(final Issue alpha, final Issue bravo)
{
int result;
result = compare(alpha, bravo, this.sorting);
//
return result;
}
/**
* Compare.
*
* @param alpha
* the alpha
* @param bravo
* the bravo
* @param sorting
* the sorting
* @return the int
*/
public static int compare(final Issue alpha, final Issue bravo, final Sorting sorting)
{
int result;
if (sorting == null)
{
result = 0;
}
else
{
switch (sorting)
{
default:
case ID:
result = CompareUtils.compare(getId(alpha), getId(bravo));
break;
case PROJECTID:
result = CompareUtils.compare(getProjectId(alpha), getProjectId(bravo));
break;
case CREATEDON:
result = CompareUtils.compare(getCreatedOn(alpha), getCreatedOn(bravo));
break;
case CLOSEDON:
result = CompareUtils.compare(getClosedOn(alpha), getClosedOn(bravo));
break;
}
}
//
return result;
}
/**
* Gets the closed on.
*
* @param source
* the source
* @return the closed on
*/
public static LocalDateTime getClosedOn(final Issue source)
{
LocalDateTime result;
if (source == null)
{
result = null;
}
else
{
result = source.getClosedOn();
}
//
return result;
}
/**
* Gets the created on.
*
* @param source
* the source
* @return the created on
*/
public static LocalDateTime getCreatedOn(final Issue source)
{
LocalDateTime result;
if (source == null)
{
result = null;
}
else
{
result = source.getCreatedOn();
}
//
return result;
}
/**
* Gets the id.
*
* @param source
* the source
* @return the id
*/
public static Long getId(final Issue source)
{
Long result;
if (source == null)
{
result = null;
}
else
{
result = source.getId();
}
//
return result;
}
/**
* Gets the identifier.
*
* @param source
* the source
* @return the identifier
*/
public static Long getProjectId(final Issue source)
{
Long result;
if (source == null)
{
result = null;
}
else
{
result = source.getProjectId();
}
//
return result;
}
}

View File

@ -0,0 +1,231 @@
/*
* 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 median.
*
* @param date
* the date
* @return the double
*/
public double computeMedian(final LocalDate date)
{
double result;
LongList values = new LongList();
for (Issue issue : this)
{
int age = issue.getAgeInDays(date);
values.add(Long.valueOf(age));
}
result = values.median();
//
return result;
}
/**
* Compute stat.
*
* @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)
{
if (issue.isActiveAt(date))
{
result.add(issue);
}
}
//
return result;
}
/**
* Extract actived between.
*
* @param start
* the start
* @param end
* the end
* @return the issues
*/
public Issues extractActivedBetween(final LocalDate start, final LocalDate end)
{
Issues result;
result = new Issues();
for (Issue issue : this)
{
if (issue.isActiveBetween(start, end))
{
result.add(issue);
}
}
//
return result;
}
/**
* Sort.
*
* @param sorting
* the sorting
* @return the issues
*/
public Issues sort(final IssueComparator.Sorting sorting)
{
Issues result;
sort(new IssueComparator(sorting));
result = this;
//
return result;
}
/**
* Sort by created on.
*
* @return the issues
*/
public Issues sortByCreatedOn()
{
Issues result;
result = sort(IssueComparator.Sorting.CREATEDON);
//
return result;
}
/**
* Sort by id.
*
* @return the issues
*/
public Issues sortById()
{
Issues result;
result = sort(IssueComparator.Sorting.ID);
//
return result;
}
/**
* Sort by identifier.
*
* @return the issues
*/
public Issues sortByProjectId()
{
Issues result;
result = sort(IssueComparator.Sorting.PROJECTID);
//
return result;
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2021 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.util.ArrayList;
import java.util.Collections;
/**
* The Class LongList.
*/
public class LongList extends ArrayList<Long>
{
private static final long serialVersionUID = 2724688980125113107L;
/**
* Instantiates a new stat.
*/
public LongList()
{
super();
}
/**
* Median.
*
* @return the double
*/
public double median()
{
double result;
sort();
if (this.isEmpty())
{
result = 0;
}
else if (this.size() % 2 == 0)
{
long a = get(this.size() / 2 - 1);
long b = get(this.size() / 2);
result = (a + b) / 2;
}
else
{
result = get(this.size() / 2);
}
//
return result;
}
/**
* Sort.
*/
public void sort()
{
Collections.sort(this);
}
}

View File

@ -41,6 +41,7 @@ public class Project
private Projects subProjects;
private IssueStats stats;
private LocalDateTime lastUpdate;
private Issues issues;
/**
* Instantiates a new project.
@ -64,6 +65,7 @@ public class Project
this.subProjects = new Projects();
this.childCount = 0;
this.stats = new IssueStats();
this.issues = new Issues();
}
public long getChildCount()
@ -171,6 +173,11 @@ public class Project
return result;
}
public Issues issues()
{
return this.issues;
}
public IssueStats issueStats()
{
return this.stats;

View File

@ -140,5 +140,4 @@ public class Projects extends ArrayList<Project>
//
return result;
}
}

View 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;
}
}

View File

@ -1,79 +0,0 @@
/*
* 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 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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.strings.StringList;
import fr.devinsy.xidyn.utils.XidynUtils;
/**
* The Class projectsRawPageBuilder.
*/
public class ChartBarView
{
private static Logger logger = LoggerFactory.getLogger(ChartBarView.class);
/**
* Builds the.
*
* @param title
* the title
* @param labelTitle
* the label title
* @param labels
* the labels
* @param values
* the values
* @return the string
* @throws AgirStatoolException
* the agir statool exception
*/
public static String build(final String title, final String labelTitle, final StringList labels, final StringList values) throws AgirStatoolException
{
String result;
try
{
String source = XidynUtils.load(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/chartBarView.xhtml"));
String code = XidynUtils.extractBodyContent(source);
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "chartBar"));
code = code.replace("# of Votes", labelTitle);
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(values));
result = code.toString();
}
catch (IOException exception)
{
throw new AgirStatoolException("Error building ProjectsRaw view: " + exception.getMessage(), exception);
}
//
return result;
}
}

View File

@ -1,79 +0,0 @@
/*
* 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 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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.strings.StringList;
import fr.devinsy.xidyn.utils.XidynUtils;
/**
* The Class projectsRawPageBuilder.
*/
public class ChartPolarView
{
private static Logger logger = LoggerFactory.getLogger(ChartPolarView.class);
/**
* Builds the.
*
* @param title
* the title
* @param labelTitle
* the label title
* @param labels
* the labels
* @param values
* the values
* @return the string
* @throws AgirStatoolException
* the agir statool exception
*/
public static String build(final String title, final String labelTitle, final StringList labels, final StringList values) throws AgirStatoolException
{
String result;
try
{
String source = XidynUtils.load(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/chartPolarView.xhtml"));
String code = XidynUtils.extractBodyContent(source);
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "chartPolar"));
code = code.replace("# of Votes", labelTitle);
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(values));
result = code.toString();
}
catch (IOException exception)
{
throw new AgirStatoolException("Error building ProjectsRaw view: " + exception.getMessage(), exception);
}
//
return result;
}
}

View File

@ -20,7 +20,6 @@ package org.april.agirstatool.core.pages;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import org.apache.commons.codec.digest.DigestUtils;
import org.april.agirstatool.charts.DateCountList;
@ -37,9 +36,9 @@ import fr.devinsy.xidyn.utils.XidynUtils;
/**
* The Class projectsRawPageBuilder.
*/
public class CreatedConcludedCountChartView
public class CreatedClosedCountChartView
{
private static Logger logger = LoggerFactory.getLogger(CreatedConcludedCountChartView.class);
private static Logger logger = LoggerFactory.getLogger(CreatedClosedCountChartView.class);
/**
* Builds the.
@ -64,21 +63,20 @@ public class CreatedConcludedCountChartView
{
if (project.hasIssue())
{
String source = XidynUtils.load(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/chartLineView.xhtml"));
String source = XidynUtils.load(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/createdClosedCountChartView.xhtml"));
String code = XidynUtils.extractBodyContent(source);
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "lineChart"));
StringList labels = buildWeekLabels(start, end);
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
StringList labels = AgirStatoolUtils.buildWeekLabels(start, end);
DateCountList dates = project.issueStats().getWeekCreatedIssueCounts();
StringList values = AgirStatoolUtils.normalizedWeekCountList(dates, start, end).toValueList();
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(values));
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(labels, values));
dates = project.issueStats().getWeekConcludedIssueCounts();
values = AgirStatoolUtils.normalizedWeekCountList(dates, start, end).toValueList();
code = code.replaceAll("data: \\[.*\\] ", "data: " + AgirStatoolUtils.toJSonNumbers(values));
code = code.replaceAll("data: \\[.*\\] ", "data: " + AgirStatoolUtils.toJSonNumbers(labels, values));
result = code.toString();
}
@ -117,19 +115,18 @@ public class CreatedConcludedCountChartView
if (project.hasIssue())
{
String source = XidynUtils.load(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/chartLineView.xhtml"));
String source = XidynUtils.load(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/createdClosedCountChartView.xhtml"));
String code = XidynUtils.extractBodyContent(source);
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "lineBar"));
StringList labels = buildWeekLabels(project.issueStats().getFirstCreate().toLocalDate());
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
StringList labels = AgirStatoolUtils.buildWeekLabels(project.issueStats().getFirstCreate().toLocalDate());
StringList values = project.issueStats().getWeekCreatedIssueCounts().toValueList();
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(values));
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(labels, values));
values = project.issueStats().getWeekConcludedIssueCounts().toValueList();
code = code.replaceAll("data: \\[.*\\] ", "data: " + AgirStatoolUtils.toJSonNumbers(values));
code = code.replaceAll("data: \\[.*\\] ", "data: " + AgirStatoolUtils.toJSonNumbers(labels, values));
result = code.toString();
}
@ -171,69 +168,23 @@ public class CreatedConcludedCountChartView
}
/**
* Builds the previous year.
* Builds the previous 2 year.
*
* @param title
* the title
* @param project
* the project
* @param yearCount
* the year count
* @return the string
* @throws AgirStatoolException
* the agir statool exception
*/
public static String buildPreviousYear(final String title, final Project project) throws AgirStatoolException
public static String buildPreviousYear(final String title, final Project project, final int yearCount) throws AgirStatoolException
{
String result;
result = buildYear(title, project, LocalDate.now().getYear() - 1);
//
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"));
result.add(label);
date = date.plusWeeks(1);
}
}
result = buildYear(title, project, LocalDate.now().getYear() - Math.abs(yearCount));
//
return result;

View File

@ -0,0 +1,204 @@
/*
* 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.charts.DateCount;
import org.april.agirstatool.charts.DateCountList;
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 CreatedClosedDiffChartView
{
private static Logger logger = LoggerFactory.getLogger(CreatedClosedDiffChartView.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/createdClosedDiffChartView.xhtml"));
String code = XidynUtils.extractBodyContent(source);
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "line2Chart"));
DateCountList createdDates = project.issueStats().getWeekCreatedIssueCounts();
DateCountList closedDates = project.issueStats().getWeekConcludedIssueCounts();
DateCountList dates = new DateCountList(createdDates.size());
for (int dateIndex = 0; dateIndex < createdDates.size(); dateIndex++)
{
DateCount createdDate = createdDates.get(dateIndex);
DateCount closedDate = closedDates.get(dateIndex);
dates.add(new DateCount(createdDate.getDate(), createdDate.getCount() - closedDate.getCount()));
}
StringList labels = AgirStatoolUtils.buildWeekLabels(start, end);
StringList values = AgirStatoolUtils.normalizedWeekCountList(dates, start, end).toValueList();
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(labels, 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
* @param yearCount
* the year count
* @return the string
* @throws AgirStatoolException
* the agir statool exception
*/
public static String buildPreviousYear(final String title, final Project project, final int yearCount) throws AgirStatoolException
{
String result;
result = buildYear(title, project, LocalDate.now().getYear() - Math.abs(yearCount));
//
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;
}
}

View File

@ -0,0 +1,202 @@
/*
* 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);
StringList values = AgirStatoolUtils.buildWeekMinAges(project, start, end);
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(labels, values));
values = AgirStatoolUtils.buildWeekMeanAges(project, start, end);
code = code.replaceAll("data : \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(labels, values));
values = AgirStatoolUtils.buildWeekMaxAges(project, start, end);
code = code.replaceAll("data : \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(labels, values));
values = AgirStatoolUtils.buildWeekMedianAges(project, start, end);
code = code.replaceAll("data : \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(labels, 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
* @param yearCount
* the year count
* @return the string
* @throws AgirStatoolException
* the agir statool exception
*/
public static String buildPreviousYear(final String title, final Project project, final int yearCount) throws AgirStatoolException
{
String result;
result = buildYear(title, project, LocalDate.now().getYear() - Math.abs(yearCount));
//
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;
}
}

View File

@ -18,19 +18,25 @@
*/
package org.april.agirstatool.core.pages;
import java.io.IOException;
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 IssueStatChartView
public class IssueStatusChartView
{
private static Logger logger = LoggerFactory.getLogger(IssueStatChartView.class);
private static Logger logger = LoggerFactory.getLogger(IssueStatusChartView.class);
/**
* Builds the.
@ -56,8 +62,47 @@ public class IssueStatChartView
values.append(project.issueStats().getWaitingCount());
values.append(project.issueStats().getResolvedCount());
String targetTitle = title + " " + project.getName();
result = ChartBarView.build(targetTitle, targetTitle, labels, values);
result = build(title, title, labels, values);
//
return result;
}
/**
* Builds the.
*
* @param title
* the title
* @param labelTitle
* the label title
* @param labels
* the labels
* @param values
* the values
* @return the string
* @throws AgirStatoolException
* the agir statool exception
*/
public static String build(final String title, final String labelTitle, final StringList labels, final StringList values) throws AgirStatoolException
{
String result;
try
{
String source = XidynUtils.load(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/issueStatusChartView.xhtml"));
String code = XidynUtils.extractBodyContent(source);
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "chartBar"));
code = code.replace("# of Votes", labelTitle);
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(values));
result = code.toString();
}
catch (IOException exception)
{
throw new AgirStatoolException("Error building ProjectsRaw view: " + exception.getMessage(), exception);
}
//
return result;
@ -84,8 +129,7 @@ public class IssueStatChartView
values.append(project.issueStats().getActiveCount());
values.append(project.issueStats().getResolvedCount());
String targetTitle = title + " " + project.getName();
result = ChartBarView.build(targetTitle, targetTitle, labels, values);
result = build(title, title, labels, values);
//
return result;

View File

@ -18,6 +18,12 @@
*/
package org.april.agirstatool.core.pages;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import org.apache.commons.lang3.StringUtils;
import org.april.agirstatool.core.AgirStatoolException;
import org.april.agirstatool.core.Project;
import org.slf4j.Logger;
@ -26,6 +32,7 @@ import org.slf4j.LoggerFactory;
import fr.devinsy.xidyn.XidynException;
import fr.devinsy.xidyn.data.TagDataManager;
import fr.devinsy.xidyn.presenters.PresenterUtils;
import utils.BuildInformation;
/**
* The class AgirStatool.
@ -55,26 +62,58 @@ public class ProjectPage
TagDataManager data = new TagDataManager();
data.setContent("agirLink", project.getName());
data.setAttribute("agirLink", "href", "https://agir.april.org/projects/" + project.getIdentifier() + "/issues");
data.setContent("projectName", "Project " + project.getName());
data.setAttribute("projectName", "href", project.getPath());
if (StringUtils.equals(project.getIdentifier(), "all"))
{
data.setAttribute("agirLink", "href", "https://agir.april.org/issues");
}
else
{
data.setAttribute("agirLink", "href", "https://agir.april.org/projects/" + project.getIdentifier() + "/issues");
}
data.setContent("versionsup", BuildInformation.instance().version());
data.setContent("issueCreatedClosed3MonthsChart", CreatedConcludedCountChartView.buildLastMonths("Created/closed 3 months Count", project, 3));
data.setContent("issueCreatedClosed6MonthsChart", CreatedConcludedCountChartView.buildLastMonths("Created/closed 6 months Count", project, 6));
data.setContent("issueCreatedClosedPreviousYearChart", CreatedConcludedCountChartView.buildPreviousYear("Created/closed last year Count", project));
data.setContent("issueCreatedClosedFullChart", CreatedConcludedCountChartView.buildFull("Created/closed Count", project));
data.setContent("lastUpdateDate", LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH':'mm", Locale.FRANCE)));
data.setContent("issueRawChart", IssueStatChartView.build("Issue Raw Count", project));
data.setContent("issueGroupedChart", IssueStatChartView.buildGrouped("Issue Grouped Count", project));
data.setContent("unassignedRawChart", UnassignedPolarChartView.build("Unassigned Raw Count", project));
data.setContent("unassignedGroupedChart", UnassignedPolarChartView.buildGrouped("Unassigned Grouped Count", project));
data.setContent("issueCreatedClosed6MonthsChartA", CreatedConcludedCountChartView.buildLastMonths("Created/closed 6 months CountA", project, 6));
data.setContent("issueCreatedClosed6MonthsChartB", CreatedConcludedCountChartView.buildLastMonths("Created/closed 6 months CountB", project, 6));
data.setContent("createClosePrevious3YearButton", LocalDate.now().getYear() - 3);
data.setContent("createClosePrevious2YearButton", LocalDate.now().getYear() - 2);
data.setContent("createClosePreviousYearButton", LocalDate.now().getYear() - 1);
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("age3MonthsChart", IssueAgeChartView.buildLastMonths("Issue Age 3 months Chart", project, 3));
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("age6MonthsChart", IssueAgeChartView.buildLastMonths("Issue Age 6 months", project, 6));
data.setContent("createdClosed12MonthsChart", CreatedClosedCountChartView.buildLastMonths("Created/closed 12 months Count", project, 12));
data.setContent("created-Closed12MonthsChart", CreatedClosedDiffChartView.buildLastMonths("Created-closed 12 months Count", project, 12));
data.setContent("age12MonthsChart", IssueAgeChartView.buildLastMonths("Issue Age 12 months", project, 12));
data.setContent("createdClosedPrevious3YearChart", CreatedClosedCountChartView.buildPreviousYear("Created/closed year-3 Count", project, -3));
data.setContent("created-ClosedPrevious3YearChart", CreatedClosedDiffChartView.buildPreviousYear("Created-closed year-3 Count", project, -3));
data.setContent("agePrevious3YearChart", IssueAgeChartView.buildPreviousYear("Issue Age Year-3 Chart", project, -3));
data.setContent("createdClosedPrevious2YearChart", CreatedClosedCountChartView.buildPreviousYear("Created/closed year-2 Count", project, -2));
data.setContent("created-ClosedPrevious2YearChart", CreatedClosedDiffChartView.buildPreviousYear("Created-closed year-2 Count", project, -2));
data.setContent("agePrevious2YearChart", IssueAgeChartView.buildPreviousYear("Issue Age Year-2 Chart", project, -2));
data.setContent("createdClosedPreviousYearChart", CreatedClosedCountChartView.buildPreviousYear("Created/closed last year Count", project, -1));
data.setContent("created-ClosedPreviousYearChart", CreatedClosedDiffChartView.buildPreviousYear("Created-closed last year Count", project, -1));
data.setContent("agePreviousYearChart", IssueAgeChartView.buildPreviousYear("Issue Age Previous Year Chart", project, -1));
data.setContent("createdClosedFullChart", CreatedClosedCountChartView.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", IssueStatusChartView.build("Issue Raw Count", project));
data.setContent("issueGroupedChart", IssueStatusChartView.buildGrouped("Issue Grouped Count", project));
data.setContent("unassignedRawChart", UnassignedIssueChartView.build("Unassigned Raw Count", project));
data.setContent("unassignedGroupedChart", UnassignedIssueChartView.buildGrouped("Unassigned Grouped Count", project));
data.setContent("createdClosedChartMini", CreatedClosedCountChartView.buildLastMonths("Created/closed 6 months CountA", project, 6));
data.setContent("created-ClosedChartMini", CreatedClosedDiffChartView.buildLastMonths("Created-closed Count Mini", project, 6));
data.setContent("ageChartMini", IssueAgeChartView.buildLastMonths("Issue Age Chart Mini", project, 6));
String projectsRawView = ProjectsRawView.build(project);
data.setContent("projectsRawView", projectsRawView);
data.setContent("tableRawView", projectsRawView);
String projectsGroupedView = ProjectsGroupedView.build(project);
data.setContent("projectsGroupedView", projectsGroupedView);
data.setContent("tableGroupedView", projectsGroupedView);
result = PresenterUtils.dynamize("/org/april/agirstatool/core/pages/project.xhtml", data).toString();
}

View File

@ -18,52 +18,26 @@
*/
package org.april.agirstatool.core.pages;
import java.io.IOException;
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.IssueStats;
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 UnassignedPolarChartView
public class UnassignedIssueChartView
{
private static Logger logger = LoggerFactory.getLogger(UnassignedPolarChartView.class);
/**
* Builds the.
*
* @param title
* the title
* @param project
* the project
* @return the string
* @throws AgirStatoolException
* the agir statool exception
*/
public static String build(final String title, final Project project) throws AgirStatoolException
{
String result;
StringList labels = new StringList("Confirmed", "Ongoing", "Waiting", "Resolved", "Rejected", "Closed");
StringList values = new StringList();
IssueStats stats = project.issueStats();
values.append(stats.getUnassignedConfirmedCount());
values.append(stats.getUnassignedOngoingCount());
values.append(stats.getUnassignedWaitingCount());
values.append(stats.getUnassignedResolvedCount());
values.append(stats.getUnassignedRejectedCount());
values.append(stats.getUnassignedClosedCount());
String targetTitle = title + " " + project.getName();
result = ChartPolarView.build(targetTitle, targetTitle, labels, values);
//
return result;
}
private static Logger logger = LoggerFactory.getLogger(UnassignedIssueChartView.class);
/**
* Builds the grouped.
@ -79,16 +53,88 @@ public class UnassignedPolarChartView
public static String buildGrouped(final String title, final Project project) throws AgirStatoolException
{
String result;
StringList labels = new StringList("Started", "Resolved", "Concluded");
StringList values = new StringList();
IssueStats stats = project.issueStats();
values.append(stats.getUnassignedStartedCount());
values.append(stats.getUnassignedResolvedCount());
values.append(stats.getUnassignedConcludedCount());
String targetTitle = title + " " + project.getName();
result = ChartPolarView.build(targetTitle, targetTitle, labels, values);
result = build(targetTitle, targetTitle, labels, values);
//
return result;
}
/**
* Builds the.
*
* @param title
* the title
* @param project
* the project
* @return the string
* @throws AgirStatoolException
* the agir statool exception
*/
public static String build(final String title, final Project project) throws AgirStatoolException
{
String result;
StringList labels = new StringList("Confirmed", "Ongoing", "Waiting", "Resolved", "Rejected", "Closed");
StringList values = new StringList();
IssueStats stats = project.issueStats();
values.append(stats.getUnassignedConfirmedCount());
values.append(stats.getUnassignedOngoingCount());
values.append(stats.getUnassignedWaitingCount());
values.append(stats.getUnassignedResolvedCount());
values.append(stats.getUnassignedRejectedCount());
values.append(stats.getUnassignedClosedCount());
String targetTitle = title + " " + project.getName();
result = build(targetTitle, targetTitle, labels, values);
//
return result;
}
/**
* Builds the.
*
* @param title
* the title
* @param labelTitle
* the label title
* @param labels
* the labels
* @param values
* the values
* @return the string
* @throws AgirStatoolException
* the agir statool exception
*/
public static String build(final String title, final String labelTitle, final StringList labels, final StringList values) throws AgirStatoolException
{
String result;
try
{
String source = XidynUtils.load(AgirStatool.class.getResource("/org/april/agirstatool/core/pages/unassignedIssueChart.xhtml"));
String code = XidynUtils.extractBodyContent(source);
code = code.replaceAll("myChart", "myChart_" + DigestUtils.md5Hex(title + "chartPolar"));
code = code.replace("# of Votes", labelTitle);
code = code.replaceAll("labels: \\[.*\\]", "labels: " + AgirStatoolUtils.toJSonStrings(labels));
code = code.replaceAll("data: \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(values));
result = code.toString();
}
catch (IOException exception)
{
throw new AgirStatoolException("Error building ProjectsRaw view: " + exception.getMessage(), exception);
}
//
return result;

View File

@ -0,0 +1,39 @@
<?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="margin: 5px 10px 10px 10px;">
<h1><a href="index.xhtml">Agir Statool</a> <a id="" href="about.xhtml">About</a></h1>
<h2>Introduction</h2>
<p>AgirStatool is a simple statistic tool software for the April Redmine instance:</p>
<ul>
<li><a href="https://agir.april.org/">https://agir.april.org/</a></li>
</ul>
<h2>Tips</h2>
<p>Some tips:</p>
<ul>
<li>full charts: the default full chart view displays only one chart. To see another full charts, you have to click on it.</li>
<li>refresh delay: waiting for an update? Concerned pages are rebuild every 5 minutes.</li>
</ul>
<h2>License and source repository</h2>
<p>The original author of AgirStatool is Christian P. MOMON.</p>
<p>Agir Statool is a free software released under the GNU AGPL license.</p>
<p>The official source repository is the April forge:</p>
<ul>
<li><a href="https://forge.april.org/adminsys/agirstatool">https://forge.april.org/adminsys/agirstatool</a></li>
</ul>
</div>
</body>
</html>

View File

@ -59,7 +59,8 @@ h1.big
h1,
h1 a,
h1 span
h1 span,
h1 sup
{
color:#0084FF;
font-size:28px;
@ -239,7 +240,7 @@ h3 span
text-decoration: none;
display: inline-block;
font-size: 16px;
width: 110px;
width: 90px;
}
.button:hover

View File

@ -11,7 +11,7 @@
<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;">
<div style="width: 100%; height: 100%; text-align: center; margin: 0 0; border: 1px solid red;" title="Created and Closed Issue Count">
<canvas id="myChart" width="100%" height="100%"></canvas>
<script>
var ctx = document.getElementById('myChart');
@ -20,29 +20,28 @@ var myChart = new Chart(ctx,
type: 'line',
data:
{
labels: ['S01', 'S02', 'S03', 'S04', 'S05'],
datasets:
[
{
label: 'Created',
data: [2, 9, 13, 15, 22, 23],
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgba(255, 99, 132, 1)',
borderWidth: 1,
fill: true,
/* cubicInterpolationMode: 'monotone', */
lineTension: 0,
pointBorderWidth: 0.00000001
pointBorderWidth: 0.00000001,
data: [2, 9, 13, 15, 22, 23]
},
{
label: 'Concluded',
data: [1, 5, 9, 13, 15, 22] ,
label: 'Closedᴿ',
backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1,
fill: true,
lineTension: 0,
pointBorderWidth: 0.00000001
pointBorderWidth: 0.00000001,
data: [1, 5, 9, 13, 15, 22]
}
]
},
@ -57,18 +56,36 @@ var myChart = new Chart(ctx,
{
xAxes:
[{
ticks:
type: 'time',
time:
{
unit: 'month',
isoWeekday: true,
displayFormats:
{
beginAtZero: false
month: 'YYYY MMM'
}
},
distribution: 'linear',
ticks:
{
beginAtZero: false,
maxTicksLimit: 0
},
gridLines:
{
zeroLineColor: 'rgba(0, 0, 0, 0.1)',
offsetGridLines: false
}
}],
yAxes:
[{
ticks:
{
beginAtZero: false,
suggestedMax: 10
}
ticks:
{
beginAtZero: false,
suggestedMax: 10,
precision: 0
}
}]
}
}

View File

@ -0,0 +1,84 @@
<?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;" title="Active Issue Count">
<canvas id="myChart" width="100%" height="100%"></canvas>
<script>
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx,
{
type: 'line',
data:
{
datasets:
[
{
label: 'Active Issues',
backgroundColor: 'rgba(255, 159, 64, 0.2)',
borderColor: 'rgba(255, 159, 64, 1)',
borderWidth: 1,
fill: true,
/* cubicInterpolationMode: 'monotone', */
lineTension: 0,
pointBorderWidth: 0.00000001,
data: [2, 9, 13, 15, 22, 23]
},
]
},
options:
{
maintainAspectRatio: false,
title: {
display: false,
text: 'Min and Max Settings'
},
scales:
{
xAxes:
[{
type: 'time',
time:
{
unit: 'month',
isoWeekday: true,
displayFormats:
{
month: 'YYYY MMM'
}
},
distribution: 'linear',
ticks:
{
},
gridLines:
{
zeroLineColor: 'rgba(0, 0, 0, 0.1)',
offsetGridLines: false
}
}],
yAxes:
[{
ticks:
{
beginAtZero: false,
suggestedMax: 10,
precision: 0
}
}]
}
}
});
</script>
</div>
</body>
</html>

View File

@ -0,0 +1,119 @@
<?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;" title="Active Issue Age (in days)">
<canvas id="myChart" width="100%" height="100%"></canvas>
<script>
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx,
{
type: 'line',
data:
{
datasets:
[
{
label: 'min',
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgba(255, 99, 132, 1)',
borderWidth: 1,
fill: +1,
cubicInterpolationMode: 'monotone',
lineTension: 0,
pointBorderWidth: 0.00000001,
data: [2, 9, 13, 15, 22, 23],
},
{
label: 'mean',
backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1,
fill: +3,
cubicInterpolationMode: 'monotone',
lineTension: 0,
pointBorderWidth: 0.00000001,
data : [1, 5, 9, 13, 15, 22],
},
{
label: 'median',
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1,
fill: false,
cubicInterpolationMode: 'monotone',
lineTension: 0,
pointBorderWidth: 0.00000001,
data : [1, 5, 9, 13, 15, 22],
},
{
label: 'max',
backgroundColor: 'rgba(153, 102, 255, 0.2)',
borderColor: 'rgba(153, 102, 255, 1)',
borderWidth: 1,
fill: false,
cubicInterpolationMode: 'monotone',
lineTension: 0,
pointBorderWidth: 0.00000001,
data : [1, 5, 9, 13, 15, 22],
}
]
},
options:
{
maintainAspectRatio: false,
title: {
display: false,
text: 'Active Issue Age'
},
scales:
{
xAxes:
[{
type: 'time',
time:
{
unit: 'month',
isoWeekday: true,
displayFormats:
{
month: 'YYYY MMM'
}
},
distribution: 'linear',
ticks:
{
beginAtZero: false,
maxTicksLimit: 0
},
gridLines:
{
zeroLineColor: 'rgba(0, 0, 0, 0.1)',
offsetGridLines: false
}
}],
yAxes:
[{
ticks:
{
beginAtZero: false,
suggestedMax: 10,
precision: 0
}
}]
}
}
});
</script>
</div>
</body>
</html>

View File

@ -11,7 +11,7 @@
<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;">
<div style="width: 100%; height: 100%; text-align: center; margin: 0 0; border: 1px solid red;" title="Issue Status Count">
<canvas id="myChart" width="100%" height="100%"></canvas>
<script>
var ctx = document.getElementById('myChart');
@ -62,7 +62,9 @@ var myChart = new Chart(ctx,
[{
ticks:
{
beginAtZero: true
beginAtZero: true,
suggestedMax: 10,
precision: 0
}
}]
}

View File

@ -11,124 +11,185 @@
<script src="Chart.bundle.min.js"></script>
</head>
<body>
<div style="margin: 10px;">
<h1><a href="index.xhtml">Agir Statool</a> Project <a id="agirLink" href="#">n/a</a></h1>
<div>
<div style="margin: 5px 10px 10px 10px;">
<h1><a href="index.xhtml">Agir Statool</a><sup id="versionsup" style="font-size: 9px;">v0.0.14</sup> <a id="projectName" href="#">n/a</a> <a id="agirLink" href="#">Link to Agir</a> <a href="about.xhtml">About</a><span style="font-size: 9px; float: right;">Page updated on<br/><span id="lastUpdateDate" style="font-size: 9px;">xx/xx/xxxx xx:xx</span></span></h1>
<div id="mainCharts">
<div style="margin: 5px;">
<a id="createClose3MonthsButton" href="#" class="button" onclick="javascript:createClosedSelect('3months');">3 months</a>
<a id="createClose6MonthsButton" href="#" class="button" onclick="javascript:createClosedSelect('6months');">6 months</a>
<a id="createCloseFullButton" href="#" class="button selected" onclick="javascript:createClosedSelect('full');">Full</a>
<a id="createClose12MonthsButton" href="#" class="button selected" onclick="javascript:createClosedSelect('12months');">12 months</a>
<a id="createCloseFullButton" href="#" class="button" onclick="javascript:createClosedSelect('full');">Full</a>
<a id="createClosePrevious3YearButton" href="#" class="button" onclick="javascript:createClosedSelect('previous3Year');">Year - 3</a>
<a id="createClosePrevious2YearButton" href="#" class="button" onclick="javascript:createClosedSelect('previous2Year');">Year - 2</a>
<a id="createClosePreviousYearButton" href="#" class="button" onclick="javascript:createClosedSelect('previousYear');">Previous Year</a>
<span style="margin-left: 100px;"> </span>
<a href="#part2" class="button">Down</a>
<span style="margin-left: 25px;"> </span>
<a href="#rawgroupedswitch" class="button" title="Go down to the table below.">⇊ ⇊</a>
<span style="margin-left: 25px;"> </span>
<a href="index.xhtml" class="button">Root</a>
<a href="admins.xhtml" class="button">Admins</a>
<a href="chapril.xhtml" class="button">Chapril</a>
<a href="gdtc.xhtml" class="button">gDTC</a>
</div>
<div id="3MonthsBox" style="display: none;">
<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: 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 id="6MonthsBox" style="display: none;">
<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: 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 id="12MonthsBox" style="">
<div id="createdClosed12MonthsChart" style="display: inline-block; width: 33%; height: 400px;">CREATED/CLOSED 12 MONTHS CHART</div>
<div id="created-Closed12MonthsChart" style="display: inline-block; width: 33%; height: 400px;">CREATED-CLOSED 12 MONTHS CHART</div>
<div id="age12MonthsChart" style="display: inline-block; width: 33%; height: 400px;">AGE 12 MONTHS CHART</div>
</div>
<div id="previous3YearBox" style="display: none;">
<div id="createdClosedPrevious3YearChart" style="display: inline-block; width: 33%; height: 400px;">CREATED/CLOSED PREVIOUS 3 YEARS CHART</div>
<div id="created-ClosedPrevious3YearChart" style="display: inline-block; width: 33%; height: 400px;">CREATED-CLOSED PREVIOUS 3 YEARS CHART</div>
<div id="agePrevious3YearChart" style="display: inline-block; width: 33%; height: 400px;">AGE PREVIOUS 3 YEARS CHART</div>
</div>
<div id="previous2YearBox" style="display: none;">
<div id="createdClosedPrevious2YearChart" style="display: inline-block; width: 33%; height: 400px;">CREATED/CLOSED PREVIOUS 2 YEARS CHART</div>
<div id="created-ClosedPrevious2YearChart" style="display: inline-block; width: 33%; height: 400px;">CREATED-CLOSED PREVIOUS 2 YEARS CHART</div>
<div id="agePrevious2YearChart" style="display: inline-block; width: 33%; height: 400px;">AGE PREVIOUS 2 YEARS CHART</div>
</div>
<div id="previousYearBox" style="display: none;">
<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: 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 id="fullBox" style="display: none;">
<div id="createdClosedFullChart" style="height: 400px;" onclick="javascript: selectMainChart('C-C');">CREATED/CLOSED FULL CHART</div>
<div id="created-ClosedFullChart" style="display: none; height: 400px;" 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 id="issueCreatedClosed3MonthsChart" style="display: none; width: 50%; height: 400px;">CREATED/CLOSED 3 MONTHS CHART</div>
<div id="issueCreatedClosed6MonthsChart" style="display: none; width: 50%; height: 400px;">CREATED/CLOSED 6 MONTHS CHART</div>
<div id="issueCreatedClosedPreviousYearChart" style="display: none; width: 50%; height: 400px;">CREATED/CLOSED PREVIOUS YEAR CHART</div>
<div id="issueCreatedClosedFullChart" style="height: 400px;">CREATED/CLOSED FULL CHART</div>
</div>
<div id="part2" style="margin: 4px;">
<div id="rawgroupedswitch" style="margin: 4px;">
<span style="display: inline-block; padding-top: 6px; vertical-align: text-top;"><a href="#part2">Grouped</a></span>
<label class="switch">
<input type="checkbox" onclick="javascript:projectsViewFlip();" />
<span class="slider round"></span>
</label>
</div>
<div id="rawView">
<div>
<div id="secondaryCharts">
<div id="issueRawChart" style="width: 400px; height: 200px; display: inline-block;">ISSUES BAR CHART</div>
<div id="issueGroupedChart" style="width: 400px; height: 200px; display: none;">ISSUES BAR CHART</div>
<div id="unassignedRawChart" style="width: 360px; height: 200px; display: inline-block;"></div>
<div id="issueCreatedClosed6MonthsChartA" style="width: 340px; height: 200px; display: inline-block;">CREATED/CLOSED 6 MONTHS CHART</div>
</div>
<br/>
<div>
<div id="projectsRawView">RAW VIEW PLACE</div>
</div>
<div id="unassignedGroupedChart" style="width: 360px; height: 200px; display: none;"></div>
<div id="createdClosedChartMini" style="width: 220px; height: 200px; display: inline-block;">CREATED/CLOSED CHART MINI</div>
<div id="created-ClosedChartMini" style="width: 220px; height: 200px; display: inline-block;">CREATED-CLOSED CHART MINI</div>
<div id="ageChartMini" style="width: 220px; height: 200px; display: inline-block;">CREATED-CLOSED MONTHS CHART MINI</div>
</div>
<div id="groupedView" style="display: none;">
<div>
<div id="issueGroupedChart" style="width: 400px; height: 200px; display: inline-block;">ISSUES BAR CHART</div>
<div id="unassignedGroupedChart" style="width: 360px; height: 200px; display: inline-block;"></div>
<div id="issueCreatedClosed6MonthsChartB" style="width: 340px; height: 200px; display: inline-block;">CREATED/CLOSED 6 MONTHS CHARTB</div>
</div>
<br/>
<div>
<div id="projectsGroupedView">GROUPED VIEW PLACE</div>
</div>
<br/>
<div id="tableView">
<div id="tableRawView">TABLE RAW VIEW</div>
<div id="tableGroupedView" style="display: none;">TABLE GROUPED VIEW</div>
</div>
</div>
<script type="text/javascript">
function createClosedSelect(selection)
{
if (selection == '3months')
document.getElementById ('createClose3MonthsButton').classList.remove('selected');
document.getElementById ('createClose6MonthsButton').classList.remove('selected');
document.getElementById ('createClose12MonthsButton').classList.remove('selected');
document.getElementById ('createClosePrevious3YearButton').classList.remove('selected');
document.getElementById ('createClosePrevious2YearButton').classList.remove('selected');
document.getElementById ('createClosePreviousYearButton').classList.remove('selected');
document.getElementById ('createCloseFullButton').classList.remove('selected');
document.getElementById ('3MonthsBox').style.display = 'none';
document.getElementById ('6MonthsBox').style.display = 'none';
document.getElementById ('12MonthsBox').style.display = 'none';
document.getElementById ('previous3YearBox').style.display = 'none';
document.getElementById ('previous2YearBox').style.display = 'none';
document.getElementById ('previousYearBox').style.display = 'none';
document.getElementById ('fullBox').style.display = 'none';
if (selection == '3months')
{
document.getElementById ('createClose3MonthsButton').classList.add('selected');
document.getElementById ('createClose6MonthsButton').classList.remove('selected');
document.getElementById ('createClosePreviousYearButton').classList.remove('selected');
document.getElementById ('createCloseFullButton').classList.remove('selected');
document.getElementById ('issueCreatedClosed3MonthsChart').style.display = 'block';
document.getElementById ('issueCreatedClosed6MonthsChart').style.display = 'none';
document.getElementById ('issueCreatedClosedPreviousYearChart').style.display = 'none';
document.getElementById ('issueCreatedClosedFullChart').style.display = 'none';
document.getElementById ('3MonthsBox').style.display = 'block';
}
else if (selection == '6months')
{
document.getElementById ('createClose3MonthsButton').classList.remove('selected');
document.getElementById ('createClose6MonthsButton').classList.add('selected');
document.getElementById ('createClosePreviousYearButton').classList.remove('selected');
document.getElementById ('createCloseFullButton').classList.remove('selected');
document.getElementById ('issueCreatedClosed3MonthsChart').style.display = 'none';
document.getElementById ('issueCreatedClosed6MonthsChart').style.display = 'block';
document.getElementById ('issueCreatedClosedPreviousYearChart').style.display = 'none';
document.getElementById ('issueCreatedClosedFullChart').style.display = 'none';
document.getElementById ('6MonthsBox').style.display = 'block';
}
else if (selection == '12months')
{
document.getElementById ('createClose12MonthsButton').classList.add('selected');
document.getElementById ('12MonthsBox').style.display = 'block';
}
else if (selection == 'previous3Year')
{
document.getElementById ('createClosePrevious3YearButton').classList.add('selected');
document.getElementById ('previous3YearBox').style.display = 'block';
}
else if (selection == 'previous2Year')
{
document.getElementById ('createClosePrevious2YearButton').classList.add('selected');
document.getElementById ('previous2YearBox').style.display = 'block';
}
else if (selection == 'previousYear')
{
document.getElementById ('createClose3MonthsButton').classList.remove('selected');
document.getElementById ('createClose6MonthsButton').classList.remove('selected');
document.getElementById ('createClosePreviousYearButton').classList.add('selected');
document.getElementById ('createCloseFullButton').classList.remove('selected');
document.getElementById ('issueCreatedClosed3MonthsChart').style.display = 'none';
document.getElementById ('issueCreatedClosed6MonthsChart').style.display = 'none';
document.getElementById ('issueCreatedClosedPreviousYearChart').style.display = 'block';
document.getElementById ('issueCreatedClosedFullChart').style.display = 'none';
document.getElementById ('previousYearBox').style.display = 'block';
}
else if (selection == 'full')
{
document.getElementById ('createClose3MonthsButton').classList.remove('selected');
document.getElementById ('createClose6MonthsButton').classList.remove('selected');
document.getElementById ('createClosePreviousYearButton').classList.remove('selected');
document.getElementById ('createCloseFullButton').classList.add('selected');
document.getElementById ('issueCreatedClosed3MonthsChart').style.display = 'none';
document.getElementById ('issueCreatedClosed6MonthsChart').style.display = 'none';
document.getElementById ('issueCreatedClosedPreviousYearChart').style.display = 'none';
document.getElementById ('issueCreatedClosedFullChart').style.display = 'block';
document.getElementById ('fullBox').style.display = 'block';
}
}
</script>
<script type="text/javascript">
var showRawView = true;
var showView = 'RAW';
function projectsViewFlip ()
{
if (showRawView == true)
if (showView == 'GROUPED')
{
document.getElementById ('rawView').style.display = 'none';
document.getElementById ('groupedView').style.display = 'inline';
showRawView = false;
document.getElementById ('issueRawChart').style.display = 'inline-block';
document.getElementById ('issueGroupedChart').style.display = 'none';
document.getElementById ('unassignedRawChart').style.display = 'inline-block';
document.getElementById ('unassignedGroupedChart').style.display = 'none';
document.getElementById ('tableRawView').style.display = 'block';
document.getElementById ('tableGroupedView').style.display = 'none';
showView = 'RAW';
}
else
{
document.getElementById ('rawView').style.display = 'block';
document.getElementById ('groupedView').style.display = 'none';
showRawView = true;
document.getElementById ('issueRawChart').style.display = 'none';
document.getElementById ('issueGroupedChart').style.display = 'inline-block';
document.getElementById ('unassignedRawChart').style.display = 'none';
document.getElementById ('unassignedGroupedChart').style.display = 'inline-block';
document.getElementById ('tableRawView').style.display = 'none';
document.getElementById ('tableGroupedView').style.display = 'block';
showView = 'GROUPED';
}
}
</script>
<script type="text/javascript">
function selectMainChart(selection)
{
document.getElementById ('createdClosedFullChart').style.display = 'none';
document.getElementById ('created-ClosedFullChart').style.display = 'none';
document.getElementById ('ageFullChart').style.display = 'none';
if (selection == 'CC')
{
document.getElementById ('createdClosedFullChart').style.display = 'block';
}
else if (selection == 'C-C')
{
document.getElementById ('created-ClosedFullChart').style.display = 'block';
}
else if (selection == 'AGE')
{
document.getElementById ('ageFullChart').style.display = 'block';
}
}
</script>

View File

@ -29,6 +29,7 @@
<th class="tablesubtitle">Rejected</th>
<th class="tablesubtitle">Closed</th>
<th class="tablesubtitle">Total</th>
<th class="tablesubtitle">Maybe</th>
<th class="tablesubtitle">New</th>
<th class="tablesubtitle">Confirmed</th>
@ -54,11 +55,11 @@
<td id="prl_closedIssueCount" class="td_number">n/a</td>
<td id="prl_issueCount" class="td_number comment">n/a</td>
<td id="prl_unassignedMaybeIssueCount" class="td_number">n/a</td>
<td id="prl_unassignedNewIssueCount" class="td_number">n/a</td>
<td id="prl_unassignedConfirmedIssueCount" class="td_number">n/a</td>
<td id="prl_unassignedOngoingIssueCount" class="td_number">n/a</td>
<td id="prl_unassignedWaitingIssueCount" class="td_number">n/a</td>
<td id="prl_unassignedMaybeIssueCount" class="td_number">n/a</td>
<td id="prl_unassignedResolvedIssueCount" class="td_number">n/a</td>
<td id="prl_unassignedRejectedIssueCount" class="td_number">n/a</td>
<td id="prl_unassignedClosedIssueCount" class="td_number">n/a</td>

View File

@ -11,7 +11,7 @@
<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;">
<div style="width: 100%; height: 100%; text-align: center; margin: 0 0; border: 1px solid red;" title="Unassgined Issue Count">
<canvas id="myChart" width="100%" height="100%"></canvas>
<script>
var ctx = document.getElementById('myChart');
@ -59,7 +59,15 @@ var myChart = new Chart(ctx,
{
display: true,
position: 'right'
}
},
scale:
{
ticks:
{
precision: 0,
suggestedMax: 5
}
}
}
});
</script>

View File

@ -0,0 +1,104 @@
/*
* Copyright (C) 2019-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.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.SignStyle;
import java.time.temporal.IsoFields;
import java.util.Locale;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* The Class JugaTest.
*
* @author Christian Pierre MOMON
*/
public class AgirStatoolTest
{
private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AgirStatoolTest.class);
@Test
public void testExport01() throws Exception
{
//
logger.debug("===== test starting...");
//
logger.debug("===== test done.");
}
@Test
public void testWeek() throws Exception
{
//
logger.debug("===== test starting...");
System.out.println("==> " + LocalDate.now().getDayOfWeek());
System.out.println("==> " + LocalDate.now().getDayOfWeek().getValue());
System.out.println("==> " + AgirStatoolUtils.normaliseWeekDate(LocalDate.now()));
System.out.println("==> " + AgirStatoolUtils.toYearWeek(LocalDate.of(2019, 12, 30)));
System.out.println(LocalDate.of(2019, 12, 30).format(DateTimeFormatter.ofPattern("yyyyww", Locale.FRENCH)));
System.out.println(LocalDate.of(2019, 12, 30).format(DateTimeFormatter.ofPattern("YYYYww", Locale.FRENCH)));
System.out.println(LocalDate.of(2019, 12, 30).format(DateTimeFormatter.ISO_WEEK_DATE));
DateTimeFormatter weekDateFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendValue(IsoFields.WEEK_BASED_YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
.appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2)
.toFormatter(Locale.FRANCE);
System.out.println(LocalDate.of(2019, 12, 30).format(weekDateFormatter));
//
logger.debug("===== test done.");
}
/**
* After class.
*
* @throws AgirStatoolException
* the Juga exception
*/
@AfterClass
public static void afterClass() throws AgirStatoolException
{
}
/**
* Before class.
*
* @throws AgirStatoolException
* the Juga exception
*/
@BeforeClass
public static void beforeClass() throws AgirStatoolException
{
BasicConfigurator.configure();
Logger.getRootLogger().setLevel(Level.DEBUG);
}
}

View File

@ -1,71 +0,0 @@
/*
* Copyright (C) 2019 Christian Pierre MOMON, DEVINSY
*
* This file is part of Juga, simple key value database.
*
* Juga 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.
*
* Juga 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 Juga. If not, see <http://www.gnu.org/licenses/>.
*/
package org.april.agirstatool.core;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.april.agirstatool.core.AgirStatoolException;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* The Class JugaTest.
*
* @author Christian Pierre MOMON
*/
public class JugaTest
{
private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(JugaTest.class);
@Test
public void testExport01() throws Exception
{
//
logger.debug("===== test starting...");
//
logger.debug("===== test done.");
}
/**
* After class.
*
* @throws AgirStatoolException
* the Juga exception
*/
@AfterClass
public static void afterClass() throws AgirStatoolException
{
}
/**
* Before class.
*
* @throws AgirStatoolException
* the Juga exception
*/
@BeforeClass
public static void beforeClass() throws AgirStatoolException
{
BasicConfigurator.configure();
Logger.getRootLogger().setLevel(Level.DEBUG);
}
}