Skip to content

Commit

Permalink
starting to refactor date rollup
Browse files Browse the repository at this point in the history
  • Loading branch information
justinbmeyer committed Jul 21, 2024
1 parent f445302 commit c309ef7
Show file tree
Hide file tree
Showing 26 changed files with 58,231 additions and 905 deletions.
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"fe:css:build": "npx tailwindcss -i ./public/css/steerco-reporting.css -o ./public/dist/production.css --watch --minify",
"fe:js:build:dev": "BUILD_MINIFY=NO rollup -c -w --sourcemap",
"fe:js:build": "rollup -c -w --sourcemap",
"test": "./node_modules/.bin/vitest"
"test": "node node_modules/vitest/vitest.mjs"
},
"keywords": [],
"author": "",
Expand All @@ -30,6 +30,7 @@
"live-server": "^1.2.2",
"rollup": "^4.5.1",
"rollup-plugin-delete": "^2.0.0",
"semver": "^7.6.3",
"tailwindcss": "^3.3.3",
"vitest": "^1.6.0"
}
Expand Down
58,232 changes: 57,459 additions & 773 deletions public/dist/main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/dist/main.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/dist/production.css

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion public/gantt-grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,11 @@ export class GanttGrid extends StacheElement {
showTooltip(event.currentTarget, issue);
}
showPercentCompleteTooltip(event, issue) {

// we should get all the children ...
const keyToChildren = Object.groupBy(this.percentComplete.issues, i => i.parentKey)
const children = keyToChildren[issue["Issue key"]];

console.log(issue, children);
showTooltipContent(event.currentTarget, percentCompleteTooltip(
{ issue,
children,
Expand Down
36 changes: 36 additions & 0 deletions public/jira/derived/derive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {deriveWorkTiming} from "./work-timing/work-timing.js";
import {getWorkStatus} from "./work-status/work-status.js";
import { normalizeIssue } from "../normalized/normalize.js";

/**
* @typedef {import("../normalized/normalize.js").NormalizedIssue & {
* derivedTiming: import("./work-timing/work-timing.js").DerivedTiming
* } & {derivedStatus: import("./work-status/work-status.js").DerivedWorkStatus}} DerivedWorkIssue
*/


/**
* Adds derived data
* @param {NormalizedIssue} normalizedIssue
* @return {DerivedWorkIssue}
*/
export function deriveIssue(issue, options){
const timing = deriveWorkTiming(issue, options);
return {

derivedTiming: timing,
derivedStatus: getWorkStatus(issue, options),
...issue
}
}



/**
*
* @param {Array<JiraIssue>} issues
* @returns {Array<DerivedWorkIssue>}
*/
export function normalizeAndDeriveIssues(issues, options) {
return issues.map( issue => deriveIssue( normalizeIssue(issue, options), options ) )
}
9 changes: 8 additions & 1 deletion public/jira/derived/work-status/work-status.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { getStatusCategoryDefault } from "../../../status-helpers";

/**
*
* @typedef {{
* statusType: string,
* workType: string
* }} DerivedWorkStatus
*/

/**
* @param {NormalizedIssue} normalizedIssue
* @return {DerivedWorkStatus}
*/
export function getWorkStatus(
normalizedIssue,
Expand Down
144 changes: 75 additions & 69 deletions public/jira/derived/work-timing/work-timing.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,7 @@ import { getWorkStatus } from "../work-status/work-status.js";
return 50
}

/**
* @typedef {NormalizedIssue & {
* derivedWork: DerivedWork
* }} DerivedWorkIssue
*/

/**
*
* @param {Array<JiraIssue>} issues
* @returns {Array<DerivedWorkIssue>}
*/
export function normalizeAndDeriveIssues(issues) {
return issues.map( issue => derivedWorkIssue( normalizeIssue(issue) ) )
}
/**
* Adds derived data
* @param {NormalizedIssue} normalizedIssue
* @return {DerivedWorkIssue}
*/

/**
*
Expand All @@ -42,12 +24,17 @@ export function getDefaultStoryPointsDefault(team) {
return team.velocity / team.parallelWorkLimit;
}

export function derivedWorkIssue(normalizedIssue, {

/**
*
* @param {import("../../normalized/normalize.js").NormalizedIssue} normalizedIssue
* @param {*} param1
* @returns {DerivedTiming}
*/
export function deriveWorkTiming(normalizedIssue, {
getDefaultConfidence = getDefaultConfidenceDefault,
getDefaultStoryPoints = getDefaultStoryPointsDefault,
uncertaintyWeight = 80,
getStatusType,
getWorkTypeDefault
uncertaintyWeight = 80
} = {}){

const isConfidenceValid = isConfidenceValueValid(normalizedIssue.confidence),
Expand Down Expand Up @@ -95,54 +82,73 @@ export function derivedWorkIssue(normalizedIssue, {
const completedDaysOfWork = getSelfCompletedDays(startData, dueData, totalDaysOfWork);

return {
...normalizedIssue,
derivedWork: {
isConfidenceValid,
usedConfidence,

isStoryPointsValid,
defaultOrStoryPoints,
storyPointsDaysOfWork,

isStoryPointsMedianValid,
defaultOrStoryPointsMedian,
storyPointsMedianDaysOfWork,

deterministicExtraPoints,
deterministicExtraDaysOfWork,
deterministicTotalPoints,
deterministicTotalDaysOfWork,

probablisticExtraPoints,
probablisticExtraDaysOfWork,
probablisticTotalPoints,
probablisticTotalDaysOfWork,

hasStartAndDueDate,
startAndDueDateDaysOfWork,

hasSprintStartAndEndDate,
sprintDaysOfWork,

sprintStartData,
endSprintData,
startData,
dueData,

totalDaysOfWork,
defaultOrTotalDaysOfWork,
completedDaysOfWork,
// TODO: This should not be calling getWorkStatus here ... something else should be doing that
// probably derived/derive.js
// This function should probably just be returning the derivedWork object itself and
// let derived/derive.js add all the sub-function's details
...getWorkStatus(normalizedIssue, {getStatusType,getWorkTypeDefault})
}
isConfidenceValid,
usedConfidence,

isStoryPointsValid,
defaultOrStoryPoints,
storyPointsDaysOfWork,

isStoryPointsMedianValid,
defaultOrStoryPointsMedian,
storyPointsMedianDaysOfWork,

deterministicExtraPoints,
deterministicExtraDaysOfWork,
deterministicTotalPoints,
deterministicTotalDaysOfWork,

probablisticExtraPoints,
probablisticExtraDaysOfWork,
probablisticTotalPoints,
probablisticTotalDaysOfWork,

hasStartAndDueDate,
startAndDueDateDaysOfWork,

hasSprintStartAndEndDate,
sprintDaysOfWork,

sprintStartData,
endSprintData,

...startData,
...dueData,

totalDaysOfWork,
defaultOrTotalDaysOfWork,
completedDaysOfWork
}
}



/**
* @typedef {{
* isConfidenceValid: boolean,
* usedConfidence: number,
* isStoryPointsValid: boolean,
* defaultOrStoryPoints: number,
* storyPointsDaysOfWork: number,
* deterministicTotalPoints: number,
* isStoryPointsMedianValid: boolean,
* defaultOrStoryPointsMedian: number,
* storyPointsMedianDaysOfWork: number,
* deterministicExtraDaysOfWork: number,
* deterministicTotalDaysOfWork: number,
* probablisticExtraDaysOfWork: number,
* probablisticTotalDaysOfWork: number,
* hasStartAndDueDate: boolean,
* hasSprintStartAndEndDate: boolean,
* sprintDaysOfWork: number | null,
* startAndDueDateDaysOfWork: number | null,
* totalDaysOfWork: number | null,
* defaultOrTotalDaysOfWork: number | null,
* completedDaysOfWork: number,
* startData: ,
* dueData: ,
* } & import("../../../shared/issue-data/date-data.js").StartData & import("../../../shared/issue-data/date-data.js").DueData
* } DerivedTiming
*/


export function isConfidenceValueValid(value){
Expand Down Expand Up @@ -191,9 +197,9 @@ export function derivedToCSVFormat(derivedIssue) {
"Issue Type": derivedIssue.type,
"Parent Link": derivedIssue.parentKey,
"Status": derivedIssue.status,
workType: derivedIssue.derivedWork.workType,
workingBusinessDays: derivedIssue.derivedWork.totalDaysOfWork,
weightedEstimate: derivedIssue.derivedWork.deterministicTotalPoints
workType: derivedIssue.derivedStatus.workType,
workingBusinessDays: derivedIssue.derivedTiming.totalDaysOfWork,
weightedEstimate: derivedIssue.derivedTiming.deterministicTotalPoints
}
}

Expand Down
45 changes: 14 additions & 31 deletions public/jira/normalized/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,19 @@ export function getConfidenceDefault({ fields }) {
export function getLabelsDefault({fields}) {
return fields?.labels || []
}

/**
* @typedef {{
* name: String,
* id: String,
* type: "releases",
* key: "string"
* }} NormalizedRelease
*/


export function getReleasesDefault ({fields}) {
return (fields["Fix versions"] || []).map( ({name, id})=> {
return {name, id}
return {name, id, type: "release", key: "SPECIAL:release-"+id}
});
}

Expand Down Expand Up @@ -223,34 +232,7 @@ export function getConfidenceDefault({ fields }) {
};
return data;
}
/**
* @typedef {{
* isConfidenceValid: boolean,
* usedConfidence: number,
* isStoryPointsValid: boolean,
* defaultOrStoryPoints: number,
* storyPointsDaysOfWork: number,
* deterministicTotalPoints: number,
* isStoryPointsMedianValid: boolean,
* defaultOrStoryPointsMedian: number,
* storyPointsMedianDaysOfWork: number,
* deterministicExtraDaysOfWork: number,
* deterministicTotalDaysOfWork: number,
* probablisticExtraDaysOfWork: number,
* probablisticTotalDaysOfWork: number,
* hasStartAndDueDate: boolean,
* hasSprintStartAndEndDate: boolean,
* sprintDaysOfWork: number | null,
* startAndDueDateDaysOfWork: number | null,
* totalDaysOfWork: number | null,
* defaultOrTotalDaysOfWork: number | null,
* completedDaysOfWork: number,
* startData: import("../../../shared/issue-data/date-data.js").StartData,
* dueData: import("../../../shared/issue-data/date-data.js").DueData,
* statusType: string,
* workType: string
* }} DerivedWork
*/


/**
* @typedef {{
Expand All @@ -269,7 +251,8 @@ export function getConfidenceDefault({ fields }) {
* sprints: null | Array<NormalizedSprint>,
* status: null | string,
* issue: JiraIssue,
* labels: Array<string>
* labels: Array<string>,
* releases: Array<NormalizedRelease>
* }} NormalizedIssue
*/

Expand Down
3 changes: 3 additions & 0 deletions public/jira/normalized/normalize.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import { expect, test } from 'vitest'
import { getConfidenceDefault } from './normalize.js'




test('getConfidenceDefault', () => {
expect(getConfidenceDefault({fields: {Confidence: 20}})).toBe(20);
})
14 changes: 14 additions & 0 deletions public/jira/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## Structure

Folders for issue data:

- `/raw` - helpers that operate on raw data returned from Jira
- `/normalized` - a function that takes raw data and normalizes it to useful values. For example, some
Jira configurations might use `Estimated Story Points` instead of `Story points`.
- `/derived` - helper functions that build from a SINGLE issue's normalized data. For instance, calculating
the amount of time between `start date` and `due date`.
- `/rollup` - helper functions that roll up data across multiple issues, specifically across parent/child relationships.

Folders for other data types:

- `/releases`
Loading

0 comments on commit c309ef7

Please sign in to comment.