feat: paste text and automatically create a new task
This commit is contained in:
@@ -1,10 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { createUuid } from '@/shared/create-uuid'
|
import { createUuid } from '@/shared/create-uuid'
|
||||||
|
import type { Stepable } from '../interfaces/stepable'
|
||||||
import TaskForm from './TaskForm.vue'
|
import TaskForm from './TaskForm.vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
initialSteps?: Stepable[]
|
||||||
|
}>()
|
||||||
|
|
||||||
const id = createUuid()
|
const id = createUuid()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<task-form :id="id" :action="'new'" />
|
<task-form :id="id" :initial-steps="props.initialSteps" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -14,12 +14,15 @@ const router = useRouter()
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
id: string
|
id: string
|
||||||
initialTask?: Taskable
|
initialTask?: Taskable
|
||||||
|
initialSteps?: Stepable[]
|
||||||
}>()
|
}>()
|
||||||
const id = computed(() => props.id)
|
const id = computed(() => props.id)
|
||||||
const hasTasks = computed(() => store.tasks.length > 0)
|
const hasTasks = computed(() => store.tasks.length > 0)
|
||||||
|
|
||||||
const steps = ref<Stepable[]>(
|
const steps = ref<Stepable[]>(
|
||||||
props.initialTask
|
props.initialSteps?.length
|
||||||
|
? props.initialSteps
|
||||||
|
: props.initialTask
|
||||||
? Task.fromTaskable(props.initialTask).steps
|
? Task.fromTaskable(props.initialTask).steps
|
||||||
: hasTasks.value
|
: hasTasks.value
|
||||||
? []
|
? []
|
||||||
|
|||||||
@@ -93,4 +93,40 @@ describe('adapt steps to textarea value', () => {
|
|||||||
`"9b237c28d5254f2b819fa66c853a9a60-2"`
|
`"9b237c28d5254f2b819fa66c853a9a60-2"`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('parses steps with unchecked checkbox format', () => {
|
||||||
|
const stepInTextarea = '- [ ] step with checkbox | 20'
|
||||||
|
|
||||||
|
const expectedStep = fixtureStep({
|
||||||
|
id: expect.any(String),
|
||||||
|
title: 'step with checkbox',
|
||||||
|
estimation: 20
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(adaptTextareaToSteps(stepInTextarea)).toEqual([expectedStep])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('parses steps with checked checkbox format', () => {
|
||||||
|
const stepInTextarea = '- [x] completed step | 15'
|
||||||
|
|
||||||
|
const expectedStep = fixtureStep({
|
||||||
|
id: expect.any(String),
|
||||||
|
title: 'completed step',
|
||||||
|
estimation: 15
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(adaptTextareaToSteps(stepInTextarea)).toEqual([expectedStep])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('parses checkbox steps without estimation', () => {
|
||||||
|
const stepInTextarea = '- [ ] step without estimation'
|
||||||
|
|
||||||
|
const expectedStep = fixtureStep({
|
||||||
|
id: expect.any(String),
|
||||||
|
title: 'step without estimation',
|
||||||
|
estimation: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(adaptTextareaToSteps(stepInTextarea)).toEqual([expectedStep])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const extractTitleAndEstimationFromStep = (
|
|||||||
): [string, number] => {
|
): [string, number] => {
|
||||||
const [rawTitle, rawEstimation] = rawStep
|
const [rawTitle, rawEstimation] = rawStep
|
||||||
.trim()
|
.trim()
|
||||||
.replace(/^-\s*/, '')
|
.replace(/^-\s*(\[[ x]\]\s*)?/, '')
|
||||||
.split('|')
|
.split('|')
|
||||||
const title = rawTitle.trim()
|
const title = rawTitle.trim()
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import TaskList from '@/modules/task/components/TaskList.vue'
|
import TaskList from '@/modules/task/components/TaskList.vue'
|
||||||
|
import { adaptTextareaToSteps } from '@/modules/task/infra/adaptStepsToTextarea'
|
||||||
import { useTaskStore } from '@/modules/task/stores/useTask.store'
|
import { useTaskStore } from '@/modules/task/stores/useTask.store'
|
||||||
import { computed } from 'vue'
|
import { computed, onMounted, onUnmounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const taskStore = useTaskStore()
|
const taskStore = useTaskStore()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const hasTask = computed(() => taskStore.tasks.length > 0)
|
const hasTask = computed(() => taskStore.tasks.length > 0)
|
||||||
|
|
||||||
@@ -12,6 +15,28 @@ const resetTasks = () => {
|
|||||||
taskStore.reset()
|
taskStore.reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handlePaste = (event: ClipboardEvent) => {
|
||||||
|
const clipboardText = event.clipboardData?.getData('text')
|
||||||
|
if (!clipboardText) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const steps = adaptTextareaToSteps(clipboardText)
|
||||||
|
if (steps.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
router.push({ name: 'new-task', state: { initialSteps: JSON.stringify(steps) } })
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
document.addEventListener('paste', handlePaste)
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
document.removeEventListener('paste', handlePaste)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import NewTaskForm from '@/modules/task/components/NewTaskForm.vue'
|
import NewTaskForm from '@/modules/task/components/NewTaskForm.vue'
|
||||||
|
import type { Stepable } from '@/modules/task/interfaces/stepable'
|
||||||
|
|
||||||
|
const rawInitialSteps = history.state?.initialSteps as string | undefined
|
||||||
|
const initialSteps = rawInitialSteps
|
||||||
|
? (JSON.parse(rawInitialSteps) as Stepable[])
|
||||||
|
: undefined
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="new-task">
|
<div class="new-task">
|
||||||
<NewTaskForm />
|
<NewTaskForm :initial-steps="initialSteps" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user