The chronological worklog chart shows time logged on issues based on the issue attribute.
Chart preview
Parameters
Parameter | Type | Default value | |
---|---|---|---|
UI | Code | ||
JQL | jql | JQL Autocomplete | |
Chart type | ChartType | Chart Type Picker | Bar |
Time period | Timeperiod | Time Period | Month |
Group by | Groupby | Group By Picker | Issue type |
Layout Script
Used layout: Timeseries All.
function formatTooltipAsHours(value, ratio, id, index) { return value.toFixed(2) + ' h'; } function formatQuarter(d) { if (d instanceof Date) { var q = d.getMonth(); q = parseInt(q / 3) + 1; return 'Q' + q; } return ''; } function formatHalfyear(d) { if (d instanceof Date) { var q = d.getMonth(); q = parseInt(q / 6) + 1; return 'H' + q; } return ''; } var c3arg = { onrendered: updateFrameHeight, data: chartData, grid: { y: { show: true }, x: { show: true } }, axis: { x: { type: 'timeseries', label: { text: chartData.custom.xLabel, position: 'outer-left' }, tick: { format: eval(chartData.custom.xTickFormat), culling: { max: 25 }, fit: true, multiline: false } }, y: { label: chartData.ytype } } }; if (chartData.custom && chartData.custom.tooltip) { var tooltipFunction = eval(chartData.custom.tooltip); c3arg.tooltip = { format: { value: tooltipFunction } }; } if ( chartData.custom && chartData.custom.gauge_max) { c3arg.gauge = { max: parseFloat(chartData.custom.gauge_max) }; } c3.generate(c3arg);
Data Script
import java.lang.reflect.Field; import java.math.BigDecimal; import org.apache.lucene.document.Document; import com.atlassian.jira.component.ComponentAccessor; import com.atlassian.jira.issue.DocumentIssueImpl; import com.atlassian.jira.issue.Issue; import com.atlassian.jira.issue.worklog.Worklog; import com.atlassian.jira.issue.worklog.WorklogManager; import com.atlassian.jira.jql.parser.JqlParseException; import com.atlassian.jira.jql.parser.JqlQueryParser; import com.atlassian.query.Query; import com.atlassian.jira.util.I18nHelper; import com.decadis.jira.xchart.api.ChartParam; import com.decadis.jira.xchart.api.model.Period import com.decadis.jira.xchart.api.util.DateUtils; def i18n = ComponentAccessor.getJiraAuthenticationContext().getI18nHelper(); def wlm = ComponentAccessor.getWorklogManager(); def metaCountGroup = chartBuilder.newDataCollector(); JqlQueryParser jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser.class); Query query = null; Period selectedPeriod = Period.fromString(TimePeriod); try { query = jqlQueryParser.parseQuery(JQL); } catch (JqlParseException e) { throw new IllegalArgumentException("Bad JQL: " + jql); } def groupValueExtractor = chartBuilder.getGrouper(GroupBy); Field documentField; try { documentField = DocumentIssueImpl.class.getDeclaredField("document"); documentField.setAccessible(true); for ( Issue issue : chartBuilder.getFilterUtils().performSearch(query, user) ) { Document doc = (Document) documentField.get(issue); for ( Worklog wl : wlm.getByIssue(issue) ) { String x = dateUtils.getPeriodGroup(wl.getCreated(), selectedPeriod); BigDecimal value = BigDecimal.valueOf(wl.getTimeSpent()).divide(BigDecimal.valueOf(3600), 4, BigDecimal.ROUND_HALF_UP); for ( String group : groupValueExtractor.getGroups(doc) ) { metaCountGroup.addValue(value, group, x); } } } } catch (Exception e){} metaCountGroup.fillMissingValues(); def chartData = chartBuilder.newChartData(i18n.getText("common.concepts.time.spent")); for ( String grpKey : metaCountGroup.keySet() ) { chartData.addGroupName(grpKey, groupValueExtractor.getResolvedValue(grpKey, null)); } chartData.setxFormat("%Y.%m.%d"); chartData.setPeriod(selectedPeriod); chartData.setType(ChartType); chartData.addCustomData("tooltip", "formatTooltipAsHours"); chartBuilder.getChartUtil().transformResult(metaCountGroup, chartData, true); return chartData;
If you still have questions, feel free to refer to our support team.