♻️ (feature) reverse parent child link with feature step index in feature

This commit is contained in:
Julien Calixte
2023-07-22 12:58:02 +02:00
parent c1a26ac429
commit ff11534291
6 changed files with 63 additions and 70 deletions

View File

@@ -1,17 +1,26 @@
<script setup lang="ts"> <script setup lang="ts">
import { Feature } from '@/modules/feature/feature'
import { FeatureStep } from '@/modules/feature/feature-steps' import { FeatureStep } from '@/modules/feature/feature-steps'
import { computed } from 'vue' import { computed } from 'vue'
const props = defineProps<{ const props = defineProps<{
step: FeatureStep step: FeatureStep
features: Feature[]
}>() }>()
const featuresInProgress = computed(() =>
props.features.filter((feature) => feature.status === 'doing')
)
const featuresDone = computed(() =>
props.features.filter((feature) => feature.status === 'done')
)
const remainingBlueBuckets = computed(() => const remainingBlueBuckets = computed(() =>
Math.max(0, props.step.blueBuckets - props.step.featuresDone.length) Math.max(0, props.step.blueBuckets - featuresDone.value.length)
) )
const hasFeaturesInProgress = computed( const hasFeaturesInProgress = computed(
() => props.step.featuresInProgress.length > 0 () => featuresInProgress.value.length > 0
) )
const hasFeaturesDone = computed(() => props.step.featuresInProgress.length > 0) const hasFeaturesDone = computed(() => featuresInProgress.value.length > 0)
</script> </script>
<template> <template>
@@ -21,7 +30,7 @@ const hasFeaturesDone = computed(() => props.step.featuresInProgress.length > 0)
<h5>📝</h5> <h5>📝</h5>
<ul v-if="hasFeaturesInProgress"> <ul v-if="hasFeaturesInProgress">
<li <li
v-for="feature in step.featuresInProgress" v-for="feature in featuresInProgress"
:key="feature.name" :key="feature.name"
class="bin" class="bin"
> >
@@ -35,11 +44,7 @@ const hasFeaturesDone = computed(() => props.step.featuresInProgress.length > 0)
<section class="done"> <section class="done">
<h5>📝</h5> <h5>📝</h5>
<ul v-if="hasFeaturesDone"> <ul v-if="hasFeaturesDone">
<li <li v-for="feature in featuresDone" :key="feature.name" class="bin">
v-for="feature in step.featuresDone"
:key="feature.name"
class="bin"
>
<div> <div>
{{ feature.name }} {{ feature.name }}
</div> </div>

View File

@@ -1,38 +1,29 @@
<script setup lang="ts"> <script setup lang="ts">
import FeatureStep from '@/modules/feature/FeatureStep.vue' import FeatureStep from '@/modules/feature/FeatureStep.vue'
import { Feature } from '@/modules/feature/feature'
import { createFeatureBoard } from '@/modules/feature/feature-board' import { createFeatureBoard } from '@/modules/feature/feature-board'
import { import { featureSteps } from '@/modules/feature/feature-steps'
FeatureStep as FeatureStepType,
featureSteps as initialFeatureSteps
} from '@/modules/feature/feature-steps'
import { sumElements } from '@/utils' import { sumElements } from '@/utils'
import { computed, onMounted, ref } from 'vue' import { computed, onMounted, ref } from 'vue'
const featureBoard = createFeatureBoard() const featureBoard = createFeatureBoard()
const featureSteps = ref<FeatureStepType[]>([]) const features = ref<Feature[]>([])
const allFeatures = computed(() =>
featureSteps.value.flatMap((step) => [
...step.featuresInProgress,
...step.featuresDone
])
)
const meanComplexity = computed(() => const meanComplexity = computed(() =>
sumElements(allFeatures.value.map((feature) => feature.complexity)) sumElements(features.value.map((feature) => feature.complexity))
) )
const meanLeadTime = computed(() => const meanLeadTime = computed(() =>
sumElements(allFeatures.value.map((feature) => feature.leadTime)) sumElements(features.value.map((feature) => feature.leadTime))
) )
onMounted( onMounted(() => (features.value = featureBoard.initBoard(featureSteps)))
() => (featureSteps.value = featureBoard.initBoard(initialFeatureSteps))
)
const nextDay = () => const nextDay = () => (features.value = featureBoard.nextDay(features.value))
(featureSteps.value = featureBoard.nextDay(featureSteps.value))
const getStepFeatures = (stepIndex: number) =>
features.value.filter((feature) => feature.step === stepIndex)
</script> </script>
<template> <template>
@@ -46,7 +37,12 @@ const nextDay = () =>
</div> </div>
</div> </div>
<ul class="features-steps"> <ul class="features-steps">
<FeatureStep v-for="step in featureSteps" :key="step.title" :step="step" /> <FeatureStep
v-for="step in featureSteps"
:key="step.title"
:step="step"
:features="getStepFeatures(step.stepIndex)"
/>
</ul> </ul>
</template> </template>

View File

@@ -1,40 +1,34 @@
import { FeatureStatus, FeatureStep } from '@/modules/feature/feature-steps' import { Feature } from '@/modules/feature/feature'
import { FeatureStep } from '@/modules/feature/feature-steps'
import { features } from '@/modules/feature/feature.fixture' import { features } from '@/modules/feature/feature.fixture'
import { pickRandomElement, popNElement, shuffleArray } from '@/utils' import { pickRandomElement, popNElement, shuffleArray } from '@/utils'
export const createFeatureBoard = () => { export const createFeatureBoard = () => {
const boardFeatures = shuffleArray(features) const boardFeatures = shuffleArray(features)
const initBoard = (featureSteps: FeatureStep[]): FeatureStep[] => { const initBoard = (steps: FeatureStep[]): Feature[] => {
const initialFeatures = popNElement(boardFeatures, 10) const initialFeatures = popNElement(boardFeatures, 10)
initialFeatures.forEach((feature) => { initialFeatures.forEach((feature) => {
const step = pickRandomElement(featureSteps) const step = pickRandomElement(steps)
const doingOrDone: FeatureStatus = pickRandomElement(['doing', 'done']) feature.status = pickRandomElement(['doing', 'done'])
feature.step = step.stepIndex
switch (doingOrDone) {
case 'doing':
step.featuresInProgress.push(feature)
break
case 'done':
step.featuresDone.push(feature)
break
}
}) })
return featureSteps return initialFeatures
} }
const nextDay = (featureSteps: FeatureStep[]): FeatureStep[] => { const nextDay = (features: Feature[]): Feature[] => {
featureSteps.forEach((step) => { features.forEach((feature) => {
step.featuresInProgress.forEach((feature) => feature.leadTime++) const isFeatureLive = feature.step === 0 && feature.status === 'done'
if (isFeatureLive) {
if (step.title.toLowerCase() !== 'release') { return
step.featuresDone.forEach((feature) => feature.leadTime++)
} }
feature.leadTime++
}) })
return featureSteps return features
} }
return { initBoard, nextDay } return { initBoard, nextDay }

View File

@@ -1,53 +1,43 @@
export type FeatureStatus = 'doing' | 'done'
export type FeatureStep = { export type FeatureStep = {
title: string title: string
featuresInProgress: Feature[]
featuresDone: Feature[]
blueBuckets: number blueBuckets: number
stepIndex: number
} }
export const featureSteps: FeatureStep[] = [ export const featureSteps: FeatureStep[] = [
{ {
title: 'Pitch', title: 'Pitch',
featuresInProgress: [], stepIndex: 6,
featuresDone: [],
blueBuckets: 2 blueBuckets: 2
}, },
{ {
title: 'Design', title: 'Design',
featuresInProgress: [], stepIndex: 5,
featuresDone: [],
blueBuckets: 1 blueBuckets: 1
}, },
{ {
title: 'Investigation', title: 'Investigation',
featuresInProgress: [], stepIndex: 4,
featuresDone: [],
blueBuckets: 1 blueBuckets: 1
}, },
{ {
title: 'Product design', title: 'Product design',
featuresInProgress: [], stepIndex: 3,
featuresDone: [],
blueBuckets: 2 blueBuckets: 2
}, },
{ {
title: 'Development', title: 'Development',
featuresInProgress: [], stepIndex: 2,
featuresDone: [],
blueBuckets: 2 blueBuckets: 2
}, },
{ {
title: 'UAT', title: 'UAT',
featuresInProgress: [], stepIndex: 1,
featuresDone: [],
blueBuckets: 3 blueBuckets: 3
}, },
{ {
title: 'Release', title: 'Release',
featuresInProgress: [], stepIndex: 0,
featuresDone: [],
blueBuckets: 0 blueBuckets: 0
} }
] ]

View File

@@ -1,3 +1,5 @@
import { Feature } from '@/modules/feature/feature'
const featureNames = [ const featureNames = [
'Dachshund', 'Dachshund',
'Jagdterrier', 'Jagdterrier',
@@ -204,5 +206,7 @@ const featureNames = [
export const features: Feature[] = featureNames.map((name) => ({ export const features: Feature[] = featureNames.map((name) => ({
name, name,
complexity: Math.floor(Math.random() * 5), complexity: Math.floor(Math.random() * 5),
leadTime: 0 leadTime: 0,
status: 'doing',
step: Infinity
})) }))

View File

@@ -1,5 +1,9 @@
type Feature = { export type FeatureStatus = 'doing' | 'done'
export type Feature = {
name: string name: string
complexity: number complexity: number
leadTime: number leadTime: number
status: FeatureStatus
step: number
} }