feat: add minimal task wizard
This commit is contained in:
parent
6e5501a5f1
commit
4f38f25d11
5 changed files with 105 additions and 3 deletions
|
@ -9,7 +9,7 @@
|
||||||
@close="$router.back()"
|
@close="$router.back()"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
>
|
>
|
||||||
<div class="p-4">
|
<div :class="{'p-4': padding}">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -72,6 +72,10 @@ defineProps({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
padding: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['create', 'primary', 'tertiary'])
|
const emit = defineEmits(['create', 'primary', 'tertiary'])
|
||||||
|
|
|
@ -186,7 +186,7 @@ export default defineComponent({
|
||||||
if (this.selectedCmd !== null) {
|
if (this.selectedCmd !== null) {
|
||||||
switch (this.selectedCmd.action) {
|
switch (this.selectedCmd.action) {
|
||||||
case CMD_NEW_TASK:
|
case CMD_NEW_TASK:
|
||||||
return this.$t('quickActions.newTask')
|
return this.$t('task.create.title')
|
||||||
case CMD_NEW_LIST:
|
case CMD_NEW_LIST:
|
||||||
return this.$t('quickActions.newList')
|
return this.$t('quickActions.newList')
|
||||||
case CMD_NEW_NAMESPACE:
|
case CMD_NEW_NAMESPACE:
|
||||||
|
|
|
@ -616,6 +616,12 @@
|
||||||
"select": "Select a date range",
|
"select": "Select a date range",
|
||||||
"noTasks": "Nothing to do — Have a nice day!"
|
"noTasks": "Nothing to do — Have a nice day!"
|
||||||
},
|
},
|
||||||
|
"create": {
|
||||||
|
"heading": "Create a task in {list}",
|
||||||
|
"title": "Enter the title of the new task…",
|
||||||
|
"descriptionPlaceholder": "Enter your description here…",
|
||||||
|
"description": "Add description…"
|
||||||
|
},
|
||||||
"detail": {
|
"detail": {
|
||||||
"chooseDueDate": "Click here to set a due date",
|
"chooseDueDate": "Click here to set a due date",
|
||||||
"chooseStartDate": "Click here to set a start date",
|
"chooseStartDate": "Click here to set a start date",
|
||||||
|
@ -933,7 +939,6 @@
|
||||||
"lists": "Lists",
|
"lists": "Lists",
|
||||||
"teams": "Teams",
|
"teams": "Teams",
|
||||||
"newList": "Enter the title of the new list…",
|
"newList": "Enter the title of the new list…",
|
||||||
"newTask": "Enter the title of the new task…",
|
|
||||||
"newNamespace": "Enter the title of the new namespace…",
|
"newNamespace": "Enter the title of the new namespace…",
|
||||||
"newTeam": "Enter the name of the new team…",
|
"newTeam": "Enter the name of the new team…",
|
||||||
"createTask": "Create a task in the current list ({title})",
|
"createTask": "Create a task in the current list ({title})",
|
||||||
|
|
|
@ -23,6 +23,7 @@ import UpcomingTasksComponent from '../views/tasks/ShowTasks.vue'
|
||||||
import LinkShareAuthComponent from '../views/sharing/LinkSharingAuth.vue'
|
import LinkShareAuthComponent from '../views/sharing/LinkSharingAuth.vue'
|
||||||
import ListNamespaces from '../views/namespaces/ListNamespaces.vue'
|
import ListNamespaces from '../views/namespaces/ListNamespaces.vue'
|
||||||
import TaskDetailView from '../views/tasks/TaskDetailView.vue'
|
import TaskDetailView from '../views/tasks/TaskDetailView.vue'
|
||||||
|
import CreateTask from '../views/tasks/CreateTask.vue'
|
||||||
// Team Handling
|
// Team Handling
|
||||||
import ListTeamsComponent from '../views/teams/ListTeams.vue'
|
import ListTeamsComponent from '../views/teams/ListTeams.vue'
|
||||||
// Label Handling
|
// Label Handling
|
||||||
|
@ -348,6 +349,15 @@ const router = createRouter({
|
||||||
},
|
},
|
||||||
props: route => ({ listId: Number(route.params.listId as string) }),
|
props: route => ({ listId: Number(route.params.listId as string) }),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/lists/:listId/create-task',
|
||||||
|
name: 'task.create',
|
||||||
|
component: CreateTask,
|
||||||
|
meta: {
|
||||||
|
showAsModal: true,
|
||||||
|
},
|
||||||
|
props: route => ({ listId: Number(route.params.listId as string) }),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/lists/:listId',
|
path: '/lists/:listId',
|
||||||
name: 'list.index',
|
name: 'list.index',
|
||||||
|
|
83
src/views/tasks/CreateTask.vue
Normal file
83
src/views/tasks/CreateTask.vue
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<template>
|
||||||
|
<CreateEdit
|
||||||
|
:padding="false"
|
||||||
|
:title="heading"
|
||||||
|
@primary="create"
|
||||||
|
:loading="taskService.loading"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
:placeholder="$t('task.create.title')"
|
||||||
|
class="task-title input"
|
||||||
|
@keyup.enter="create"
|
||||||
|
v-model="newTask.title"
|
||||||
|
v-focus
|
||||||
|
/>
|
||||||
|
<BaseButton
|
||||||
|
v-if="!descriptionFormVisible"
|
||||||
|
@click="() => descriptionFormVisible = true"
|
||||||
|
class="toggle-description-button"
|
||||||
|
>
|
||||||
|
{{ $t('task.create.description') }}
|
||||||
|
</BaseButton>
|
||||||
|
<editor
|
||||||
|
v-if="descriptionFormVisible"
|
||||||
|
v-model="newTask.description"
|
||||||
|
:placeholder="$t('task.create.descriptionPlaceholder')"
|
||||||
|
:preview-is-default="false"
|
||||||
|
class="m-4"
|
||||||
|
/>
|
||||||
|
</CreateEdit>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {computed, ref} from 'vue'
|
||||||
|
import {useStore} from '@/store'
|
||||||
|
import {useI18n} from 'vue-i18n'
|
||||||
|
import CreateEdit from '@/components/misc/create-edit.vue'
|
||||||
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
import TaskModel from '@/models/task'
|
||||||
|
import Editor from '@/components/input/AsyncEditor'
|
||||||
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
import TaskService from '@/services/task'
|
||||||
|
import {useRouter} from 'vue-router'
|
||||||
|
|
||||||
|
const store = useStore()
|
||||||
|
const router = useRouter()
|
||||||
|
const {t} = useI18n()
|
||||||
|
const props = defineProps<{
|
||||||
|
listId: number,
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const heading = computed(() => {
|
||||||
|
const listTitle = store.getters['lists/getListById'](props.listId)?.title || ''
|
||||||
|
return listTitle !== ''
|
||||||
|
? t('task.create.heading', {list: listTitle})
|
||||||
|
: t('task.new')
|
||||||
|
})
|
||||||
|
|
||||||
|
const descriptionFormVisible = ref(false)
|
||||||
|
const newTask = ref<ITask>(new TaskModel({}))
|
||||||
|
const taskService = ref(new TaskService())
|
||||||
|
|
||||||
|
async function create() {
|
||||||
|
newTask.value.listId = props.listId
|
||||||
|
const task = await taskService.value.create(newTask.value)
|
||||||
|
return router.push({name: 'task.detail', params: {id: task.id}})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.task-title {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
border: 0;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-description-button {
|
||||||
|
padding: 1rem;
|
||||||
|
color: var(--grey-400);
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in a new issue