fix: use props destructuring everywhere
This commit is contained in:
parent
78a268ab07
commit
3aa502e07d
@ -84,14 +84,17 @@ import ColorBubble from '@/components/misc/colorBubble.vue'
|
|||||||
import ProjectsNavigation from '@/components/home/ProjectsNavigation.vue'
|
import ProjectsNavigation from '@/components/home/ProjectsNavigation.vue'
|
||||||
import {canNestProjectDeeper} from '@/helpers/canNestProjectDeeper'
|
import {canNestProjectDeeper} from '@/helpers/canNestProjectDeeper'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const {
|
||||||
|
project,
|
||||||
|
isLoading,
|
||||||
|
canCollapse,
|
||||||
|
level = 0,
|
||||||
|
} = defineProps<{
|
||||||
project: IProject,
|
project: IProject,
|
||||||
isLoading?: boolean,
|
isLoading?: boolean,
|
||||||
canCollapse?: boolean,
|
canCollapse?: boolean,
|
||||||
level?: number,
|
level?: number,
|
||||||
}>(), {
|
}>()
|
||||||
level: 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
const projectStore = useProjectStore()
|
const projectStore = useProjectStore()
|
||||||
const baseStore = useBaseStore()
|
const baseStore = useBaseStore()
|
||||||
@ -104,12 +107,12 @@ const childProjects = computed(() => {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
return projectStore.getChildProjects(props.project.id)
|
return projectStore.getChildProjects(project.id)
|
||||||
.filter(p => !p.isArchived)
|
.filter(p => !p.isArchived)
|
||||||
.sort((a, b) => a.position - b.position)
|
.sort((a, b) => a.position - b.position)
|
||||||
})
|
})
|
||||||
|
|
||||||
const canNestDeeper = computed(() => canNestProjectDeeper(props.level))
|
const canNestDeeper = computed(() => canNestProjectDeeper(level))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, ref, toRef, watch} from 'vue'
|
import {computed, ref, watch} from 'vue'
|
||||||
import {createRandomID} from '@/helpers/randomId'
|
import {createRandomID} from '@/helpers/randomId'
|
||||||
import XButton from '@/components/input/button.vue'
|
import XButton from '@/components/input/button.vue'
|
||||||
|
|
||||||
@ -53,22 +53,16 @@ const lastChangeTimeout = ref<ReturnType<typeof setTimeout> | null>(null)
|
|||||||
const defaultColors = ref(DEFAULT_COLORS)
|
const defaultColors = ref(DEFAULT_COLORS)
|
||||||
const colorListID = ref(createRandomID())
|
const colorListID = ref(createRandomID())
|
||||||
|
|
||||||
const props = defineProps({
|
const {
|
||||||
modelValue: {
|
modelValue,
|
||||||
type: String,
|
} = defineProps<{
|
||||||
required: true,
|
modelValue: string,
|
||||||
},
|
}>()
|
||||||
menuPosition: {
|
|
||||||
type: String,
|
|
||||||
default: 'top',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
const modelValue = toRef(props, 'modelValue')
|
|
||||||
watch(
|
watch(
|
||||||
modelValue,
|
() => modelValue,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
color.value = newValue
|
color.value = newValue
|
||||||
},
|
},
|
||||||
|
@ -75,17 +75,19 @@ import BaseButton from '@/components/base/BaseButton.vue'
|
|||||||
import {ref, useAttrs, watchEffect} from 'vue'
|
import {ref, useAttrs, watchEffect} from 'vue'
|
||||||
import {useScrollLock} from '@vueuse/core'
|
import {useScrollLock} from '@vueuse/core'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const {
|
||||||
|
enabled = true,
|
||||||
|
overflow,
|
||||||
|
wide,
|
||||||
|
transitionName = 'modal',
|
||||||
|
variant = 'default',
|
||||||
|
} = defineProps<{
|
||||||
enabled?: boolean,
|
enabled?: boolean,
|
||||||
overflow?: boolean,
|
overflow?: boolean,
|
||||||
wide?: boolean,
|
wide?: boolean,
|
||||||
transitionName?: 'modal' | 'fade',
|
transitionName?: 'modal' | 'fade',
|
||||||
variant?: 'default' | 'hint-modal' | 'scrolling',
|
variant?: 'default' | 'hint-modal' | 'scrolling',
|
||||||
}>(), {
|
}>()
|
||||||
enabled: true,
|
|
||||||
transitionName: 'modal',
|
|
||||||
variant: 'default',
|
|
||||||
})
|
|
||||||
|
|
||||||
defineEmits(['close', 'submit'])
|
defineEmits(['close', 'submit'])
|
||||||
|
|
||||||
@ -95,7 +97,7 @@ const modal = ref<HTMLElement | null>(null)
|
|||||||
const scrollLock = useScrollLock(modal)
|
const scrollLock = useScrollLock(modal)
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
scrollLock.value = props.enabled
|
scrollLock.value = enabled
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -44,8 +44,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {toRef, type PropType} from 'vue'
|
|
||||||
|
|
||||||
import type {IProject} from '@/modelTypes/IProject'
|
import type {IProject} from '@/modelTypes/IProject'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
@ -53,14 +51,13 @@ import BaseButton from '@/components/base/BaseButton.vue'
|
|||||||
import {useProjectBackground} from './useProjectBackground'
|
import {useProjectBackground} from './useProjectBackground'
|
||||||
import {useProjectStore} from '@/stores/projects'
|
import {useProjectStore} from '@/stores/projects'
|
||||||
|
|
||||||
const props = defineProps({
|
const {
|
||||||
project: {
|
project,
|
||||||
type: Object as PropType<IProject>,
|
} = defineProps<{
|
||||||
required: true,
|
project: IProject,
|
||||||
},
|
}>()
|
||||||
})
|
|
||||||
|
|
||||||
const {background, blurHashUrl} = useProjectBackground(toRef(props, 'project'))
|
const {background, blurHashUrl} = useProjectBackground(project)
|
||||||
|
|
||||||
const projectStore = useProjectStore()
|
const projectStore = useProjectStore()
|
||||||
</script>
|
</script>
|
||||||
|
@ -180,13 +180,13 @@ import {useI18n} from 'vue-i18n'
|
|||||||
const taskStore = useTaskStore()
|
const taskStore = useTaskStore()
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const {
|
||||||
|
task,
|
||||||
|
editEnabled = true,
|
||||||
|
} = defineProps<{
|
||||||
task: ITask,
|
task: ITask,
|
||||||
initialAttachments?: IAttachment[],
|
|
||||||
editEnabled: boolean,
|
editEnabled: boolean,
|
||||||
}>(), {
|
}>()
|
||||||
editEnabled: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
// FIXME: this should go through the store
|
// FIXME: this should go through the store
|
||||||
const emit = defineEmits(['task-changed'])
|
const emit = defineEmits(['task-changed'])
|
||||||
@ -223,7 +223,7 @@ function uploadNewAttachment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function uploadFilesToTask(files: File[] | FileList) {
|
function uploadFilesToTask(files: File[] | FileList) {
|
||||||
uploadFiles(attachmentService, props.task.id, files)
|
uploadFiles(attachmentService, task.id, files)
|
||||||
}
|
}
|
||||||
|
|
||||||
const attachmentToDelete = ref<IAttachment | null>(null)
|
const attachmentToDelete = ref<IAttachment | null>(null)
|
||||||
@ -260,11 +260,11 @@ async function viewOrDownload(attachment: IAttachment) {
|
|||||||
const copy = useCopyToClipboard()
|
const copy = useCopyToClipboard()
|
||||||
|
|
||||||
function copyUrl(attachment: IAttachment) {
|
function copyUrl(attachment: IAttachment) {
|
||||||
copy(generateAttachmentUrl(props.task.id, attachment.id))
|
copy(generateAttachmentUrl(task.id, attachment.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setCoverImage(attachment: IAttachment | null) {
|
async function setCoverImage(attachment: IAttachment | null) {
|
||||||
const task = await taskStore.setCoverImage(props.task, attachment)
|
const task = await taskStore.setCoverImage(task, attachment)
|
||||||
emit('task-changed', task)
|
emit('task-changed', task)
|
||||||
success({message: t('task.attachment.successfullyChangedCoverImage')})
|
success({message: t('task.attachment.successfullyChangedCoverImage')})
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, shallowReactive, computed, watch, onMounted, onBeforeUnmount, toRef, type PropType} from 'vue'
|
import {ref, shallowReactive, computed, watch, onMounted, onBeforeUnmount} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import flatPickr from 'vue-flatpickr-component'
|
import flatPickr from 'vue-flatpickr-component'
|
||||||
|
|
||||||
@ -46,12 +46,12 @@ import TaskService from '@/services/task'
|
|||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
import {useAuthStore} from '@/stores/auth'
|
import {useAuthStore} from '@/stores/auth'
|
||||||
|
|
||||||
const props = defineProps({
|
const {
|
||||||
modelValue: {
|
modelValue,
|
||||||
type: Object as PropType<ITask>,
|
} = defineProps<{
|
||||||
required: true,
|
modelValue: ITask,
|
||||||
},
|
}>()
|
||||||
})
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
@ -66,7 +66,7 @@ const lastValue = ref<Date | null>()
|
|||||||
const changeInterval = ref<ReturnType<typeof setInterval>>()
|
const changeInterval = ref<ReturnType<typeof setInterval>>()
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
toRef(props, 'modelValue'),
|
() => modelValue,
|
||||||
(value) => {
|
(value) => {
|
||||||
task.value = { ...value }
|
task.value = { ...value }
|
||||||
dueDate.value = value.dueDate
|
dueDate.value = value.dueDate
|
||||||
|
@ -96,14 +96,15 @@ const router = useRouter()
|
|||||||
|
|
||||||
const loadingInternal = ref(false)
|
const loadingInternal = ref(false)
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const {
|
||||||
|
task,
|
||||||
|
loading = false,
|
||||||
|
} = defineProps<{
|
||||||
task: ITask,
|
task: ITask,
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
}>(), {
|
}>()
|
||||||
loading: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
const color = computed(() => getHexColor(props.task.hexColor))
|
const color = computed(() => getHexColor(task.hexColor))
|
||||||
|
|
||||||
async function toggleTaskDone(task: ITask) {
|
async function toggleTaskDone(task: ITask) {
|
||||||
loadingInternal.value = true
|
loadingInternal.value = true
|
||||||
@ -120,7 +121,7 @@ async function toggleTaskDone(task: ITask) {
|
|||||||
function openTaskDetail() {
|
function openTaskDetail() {
|
||||||
router.push({
|
router.push({
|
||||||
name: 'task.detail',
|
name: 'task.detail',
|
||||||
params: {id: props.task.id},
|
params: {id: task.id},
|
||||||
state: {backdropView: router.currentRoute.value.fullPath},
|
state: {backdropView: router.currentRoute.value.fullPath},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -128,12 +129,12 @@ function openTaskDetail() {
|
|||||||
const coverImageBlobUrl = ref<string | null>(null)
|
const coverImageBlobUrl = ref<string | null>(null)
|
||||||
|
|
||||||
async function maybeDownloadCoverImage() {
|
async function maybeDownloadCoverImage() {
|
||||||
if (!props.task.coverImageAttachmentId) {
|
if (!task.coverImageAttachmentId) {
|
||||||
coverImageBlobUrl.value = null
|
coverImageBlobUrl.value = null
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const attachment = props.task.attachments.find(a => a.id === props.task.coverImageAttachmentId)
|
const attachment = task.attachments.find(a => a.id === task.coverImageAttachmentId)
|
||||||
if (!attachment || !SUPPORTED_IMAGE_SUFFIX.some((suffix) => attachment.file.name.endsWith(suffix))) {
|
if (!attachment || !SUPPORTED_IMAGE_SUFFIX.some((suffix) => attachment.file.name.endsWith(suffix))) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -143,7 +144,7 @@ async function maybeDownloadCoverImage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.task.coverImageAttachmentId,
|
() => task.coverImageAttachmentId,
|
||||||
maybeDownloadCoverImage,
|
maybeDownloadCoverImage,
|
||||||
{immediate: true},
|
{immediate: true},
|
||||||
)
|
)
|
||||||
|
@ -65,7 +65,6 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, ref, watch} from 'vue'
|
import {computed, ref, watch} from 'vue'
|
||||||
import {toRef} from '@vueuse/core'
|
|
||||||
import {SECONDS_A_DAY, SECONDS_A_HOUR} from '@/constants/date'
|
import {SECONDS_A_DAY, SECONDS_A_HOUR} from '@/constants/date'
|
||||||
import {IReminderPeriodRelativeTo, REMINDER_PERIOD_RELATIVE_TO_TYPES} from '@/types/IReminderPeriodRelativeTo'
|
import {IReminderPeriodRelativeTo, REMINDER_PERIOD_RELATIVE_TO_TYPES} from '@/types/IReminderPeriodRelativeTo'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
@ -84,28 +83,27 @@ import SimpleButton from '@/components/input/SimpleButton.vue'
|
|||||||
|
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const {
|
||||||
|
modelValue,
|
||||||
|
clearAfterUpdate = false,
|
||||||
|
defaultRelativeTo = REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE,
|
||||||
|
} = defineProps<{
|
||||||
modelValue?: ITaskReminder,
|
modelValue?: ITaskReminder,
|
||||||
disabled?: boolean,
|
|
||||||
clearAfterUpdate?: boolean,
|
clearAfterUpdate?: boolean,
|
||||||
defaultRelativeTo?: null | IReminderPeriodRelativeTo,
|
defaultRelativeTo?: null | IReminderPeriodRelativeTo,
|
||||||
}>(), {
|
}>()
|
||||||
disabled: false,
|
|
||||||
clearAfterUpdate: false,
|
|
||||||
defaultRelativeTo: REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE,
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
const reminder = ref<ITaskReminder>(new TaskReminderModel())
|
const reminder = ref<ITaskReminder>(new TaskReminderModel())
|
||||||
|
|
||||||
const presets = computed<TaskReminderModel[]>(() => [
|
const presets = computed<TaskReminderModel[]>(() => [
|
||||||
{reminder: null, relativePeriod: 0, relativeTo: props.defaultRelativeTo},
|
{reminder: null, relativePeriod: 0, relativeTo: defaultRelativeTo},
|
||||||
{reminder: null, relativePeriod: -2 * SECONDS_A_HOUR, relativeTo: props.defaultRelativeTo},
|
{reminder: null, relativePeriod: -2 * SECONDS_A_HOUR, relativeTo: defaultRelativeTo},
|
||||||
{reminder: null, relativePeriod: -1 * SECONDS_A_DAY, relativeTo: props.defaultRelativeTo},
|
{reminder: null, relativePeriod: -1 * SECONDS_A_DAY, relativeTo: defaultRelativeTo},
|
||||||
{reminder: null, relativePeriod: -1 * SECONDS_A_DAY * 3, relativeTo: props.defaultRelativeTo},
|
{reminder: null, relativePeriod: -1 * SECONDS_A_DAY * 3, relativeTo: defaultRelativeTo},
|
||||||
{reminder: null, relativePeriod: -1 * SECONDS_A_DAY * 7, relativeTo: props.defaultRelativeTo},
|
{reminder: null, relativePeriod: -1 * SECONDS_A_DAY * 7, relativeTo: defaultRelativeTo},
|
||||||
{reminder: null, relativePeriod: -1 * SECONDS_A_DAY * 30, relativeTo: props.defaultRelativeTo},
|
{reminder: null, relativePeriod: -1 * SECONDS_A_DAY * 30, relativeTo: defaultRelativeTo},
|
||||||
])
|
])
|
||||||
const reminderDate = ref(null)
|
const reminderDate = ref(null)
|
||||||
|
|
||||||
@ -114,7 +112,7 @@ type availableForms = null | 'relative' | 'absolute'
|
|||||||
const showFormSwitch = ref<availableForms>(null)
|
const showFormSwitch = ref<availableForms>(null)
|
||||||
|
|
||||||
const activeForm = computed<availableForms>(() => {
|
const activeForm = computed<availableForms>(() => {
|
||||||
if (props.defaultRelativeTo === null) {
|
if (defaultRelativeTo === null) {
|
||||||
return 'absolute'
|
return 'absolute'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,9 +132,8 @@ const reminderText = computed(() => {
|
|||||||
return t('task.addReminder')
|
return t('task.addReminder')
|
||||||
})
|
})
|
||||||
|
|
||||||
const modelValue = toRef(props, 'modelValue')
|
|
||||||
watch(
|
watch(
|
||||||
modelValue,
|
() => modelValue,
|
||||||
(newReminder) => {
|
(newReminder) => {
|
||||||
reminder.value = newReminder || new TaskReminderModel()
|
reminder.value = newReminder || new TaskReminderModel()
|
||||||
},
|
},
|
||||||
@ -146,7 +143,7 @@ watch(
|
|||||||
function updateData() {
|
function updateData() {
|
||||||
emit('update:modelValue', reminder.value)
|
emit('update:modelValue', reminder.value)
|
||||||
|
|
||||||
if (props.clearAfterUpdate) {
|
if (clearAfterUpdate) {
|
||||||
reminder.value = new TaskReminderModel()
|
reminder.value = new TaskReminderModel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +165,7 @@ function setReminderFromPreset(preset, toggle) {
|
|||||||
|
|
||||||
function updateDataAndMaybeClose(toggle) {
|
function updateDataAndMaybeClose(toggle) {
|
||||||
updateData()
|
updateData()
|
||||||
if (props.clearAfterUpdate) {
|
if (clearAfterUpdate) {
|
||||||
toggle()
|
toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, watch, type PropType} from 'vue'
|
import {ref, watch} from 'vue'
|
||||||
import {toRef} from '@vueuse/core'
|
|
||||||
|
|
||||||
import {periodToSeconds, PeriodUnit, secondsToPeriod} from '@/helpers/time/period'
|
import {periodToSeconds, PeriodUnit, secondsToPeriod} from '@/helpers/time/period'
|
||||||
|
|
||||||
@ -57,16 +56,11 @@ import TaskReminderModel from '@/models/taskReminder'
|
|||||||
import type {ITaskReminder} from '@/modelTypes/ITaskReminder'
|
import type {ITaskReminder} from '@/modelTypes/ITaskReminder'
|
||||||
import {REMINDER_PERIOD_RELATIVE_TO_TYPES, type IReminderPeriodRelativeTo} from '@/types/IReminderPeriodRelativeTo'
|
import {REMINDER_PERIOD_RELATIVE_TO_TYPES, type IReminderPeriodRelativeTo} from '@/types/IReminderPeriodRelativeTo'
|
||||||
|
|
||||||
const props = defineProps({
|
const {
|
||||||
modelValue: {
|
modelValue,
|
||||||
type: Object as PropType<ITaskReminder>,
|
} = defineProps<{
|
||||||
required: false,
|
modelValue?: ITaskReminder,
|
||||||
},
|
}>()
|
||||||
disabled: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
@ -86,9 +80,8 @@ const period = ref<PeriodInput>({
|
|||||||
sign: -1,
|
sign: -1,
|
||||||
})
|
})
|
||||||
|
|
||||||
const modelValue = toRef(props, 'modelValue')
|
|
||||||
watch(
|
watch(
|
||||||
modelValue,
|
() => modelValue,
|
||||||
(value) => {
|
(value) => {
|
||||||
const p = secondsToPeriod(value?.relativePeriod)
|
const p = secondsToPeriod(value?.relativePeriod)
|
||||||
period.value.durationUnit = p.unit
|
period.value.durationUnit = p.unit
|
||||||
|
@ -41,20 +41,20 @@ import ReminderDetail from '@/components/tasks/partials/reminder-detail.vue'
|
|||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
import {REMINDER_PERIOD_RELATIVE_TO_TYPES} from '@/types/IReminderPeriodRelativeTo'
|
import {REMINDER_PERIOD_RELATIVE_TO_TYPES} from '@/types/IReminderPeriodRelativeTo'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const {
|
||||||
|
modelValue,
|
||||||
|
disabled = false,
|
||||||
|
} = defineProps<{
|
||||||
modelValue: ITask,
|
modelValue: ITask,
|
||||||
disabled?: boolean,
|
disabled?: boolean,
|
||||||
}>(), {
|
}>()
|
||||||
modelValue: [],
|
|
||||||
disabled: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
const reminders = ref<ITaskReminder[]>([])
|
const reminders = ref<ITaskReminder[]>([])
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue.reminders,
|
() => modelValue.reminders,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
reminders.value = newVal
|
reminders.value = newVal
|
||||||
},
|
},
|
||||||
@ -62,19 +62,19 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
const defaultRelativeTo = computed(() => {
|
const defaultRelativeTo = computed(() => {
|
||||||
if (typeof props.modelValue === 'undefined') {
|
if (typeof modelValue === 'undefined') {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.modelValue?.dueDate) {
|
if (modelValue?.dueDate) {
|
||||||
return REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE
|
return REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.modelValue.dueDate === null && props.modelValue.startDate !== null) {
|
if (modelValue.dueDate === null && modelValue.startDate !== null) {
|
||||||
return REMINDER_PERIOD_RELATIVE_TO_TYPES.STARTDATE
|
return REMINDER_PERIOD_RELATIVE_TO_TYPES.STARTDATE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.modelValue.dueDate === null && props.modelValue.startDate === null && props.modelValue.endDate !== null) {
|
if (modelValue.dueDate === null && modelValue.startDate === null && modelValue.endDate !== null) {
|
||||||
return REMINDER_PERIOD_RELATIVE_TO_TYPES.ENDDATE
|
return REMINDER_PERIOD_RELATIVE_TO_TYPES.ENDDATE
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ const defaultRelativeTo = computed(() => {
|
|||||||
|
|
||||||
function updateData() {
|
function updateData() {
|
||||||
emit('update:modelValue', {
|
emit('update:modelValue', {
|
||||||
...props.modelValue,
|
...modelValue,
|
||||||
reminders: reminders.value,
|
reminders: reminders.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, watch, shallowReactive, toRef, type PropType, onMounted, onBeforeUnmount, computed} from 'vue'
|
import {ref, watch, shallowReactive, onMounted, onBeforeUnmount, computed} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import TaskModel, { getHexColor } from '@/models/task'
|
import TaskModel, { getHexColor } from '@/models/task'
|
||||||
@ -153,32 +153,21 @@ import {useProjectStore} from '@/stores/projects'
|
|||||||
import {useBaseStore} from '@/stores/base'
|
import {useBaseStore} from '@/stores/base'
|
||||||
import {useTaskStore} from '@/stores/tasks'
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
const props = defineProps({
|
const {
|
||||||
theTask: {
|
theTask,
|
||||||
type: Object as PropType<ITask>,
|
isArchived = false,
|
||||||
required: true,
|
showProject = false,
|
||||||
},
|
disabled = false,
|
||||||
isArchived: {
|
showProjectColor = false,
|
||||||
type: Boolean,
|
canMarkAsDone = true,
|
||||||
default: false,
|
} = defineProps<{
|
||||||
},
|
theTask: ITask,
|
||||||
showProject: {
|
isArchived?: boolean,
|
||||||
type: Boolean,
|
showProject?: boolean,
|
||||||
default: false,
|
disabled?: boolean,
|
||||||
},
|
showProjectColor?: boolean,
|
||||||
disabled: {
|
canMarkAsDone?: boolean,
|
||||||
type: Boolean,
|
}>()
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
showProjectColor: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
canMarkAsDone: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['task-updated'])
|
const emit = defineEmits(['task-updated'])
|
||||||
|
|
||||||
@ -188,10 +177,8 @@ const taskService = shallowReactive(new TaskService())
|
|||||||
const task = ref<ITask>(new TaskModel())
|
const task = ref<ITask>(new TaskModel())
|
||||||
const showDefer = ref(false)
|
const showDefer = ref(false)
|
||||||
|
|
||||||
const theTask = toRef(props, 'theTask')
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
theTask,
|
() => theTask,
|
||||||
newVal => {
|
newVal => {
|
||||||
task.value = newVal
|
task.value = newVal
|
||||||
},
|
},
|
||||||
|
@ -14,11 +14,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {toRef} from 'vue'
|
|
||||||
import type {IProject} from '@/modelTypes/IProject'
|
import type {IProject} from '@/modelTypes/IProject'
|
||||||
import {useSavedFilter} from '@/services/savedFilter'
|
import {useSavedFilter} from '@/services/savedFilter'
|
||||||
|
|
||||||
const props = defineProps<{ projectId: IProject['id'] }>()
|
const {
|
||||||
|
projectId,
|
||||||
|
} = defineProps<{
|
||||||
|
projectId: IProject['id'],
|
||||||
|
}>()
|
||||||
|
|
||||||
const {deleteFilter} = useSavedFilter(toRef(props, 'projectId'))
|
const {deleteFilter} = useSavedFilter(projectId)
|
||||||
</script>
|
</script>
|
||||||
|
@ -54,8 +54,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {toRef} from 'vue'
|
|
||||||
|
|
||||||
import Editor from '@/components/input/AsyncEditor'
|
import Editor from '@/components/input/AsyncEditor'
|
||||||
import CreateEdit from '@/components/misc/create-edit.vue'
|
import CreateEdit from '@/components/misc/create-edit.vue'
|
||||||
import Filters from '@/components/project/partials/filters.vue'
|
import Filters from '@/components/project/partials/filters.vue'
|
||||||
@ -64,7 +62,11 @@ import {useSavedFilter} from '@/services/savedFilter'
|
|||||||
|
|
||||||
import type {IProject} from '@/modelTypes/IProject'
|
import type {IProject} from '@/modelTypes/IProject'
|
||||||
|
|
||||||
const props = defineProps<{ projectId: IProject['id'] }>()
|
const {
|
||||||
|
projectId,
|
||||||
|
} = defineProps<{
|
||||||
|
projectId: IProject['id'],
|
||||||
|
}>()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
saveFilterWithValidation,
|
saveFilterWithValidation,
|
||||||
@ -73,5 +75,5 @@ const {
|
|||||||
filterService,
|
filterService,
|
||||||
titleValid,
|
titleValid,
|
||||||
validateTitleField,
|
validateTitleField,
|
||||||
} = useSavedFilter(toRef(props, 'projectId'))
|
} = useSavedFilter(projectId)
|
||||||
</script>
|
</script>
|
||||||
|
@ -120,7 +120,7 @@ export default { name: 'List' }
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed, toRef, nextTick, onMounted, type PropType} from 'vue'
|
import {ref, computed, nextTick, onMounted} from 'vue'
|
||||||
import draggable from 'zhyswan-vuedraggable'
|
import draggable from 'zhyswan-vuedraggable'
|
||||||
import {useRoute, useRouter} from 'vue-router'
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
|
|
||||||
@ -144,12 +144,11 @@ import {useTaskStore} from '@/stores/tasks'
|
|||||||
|
|
||||||
import type {IProject} from '@/modelTypes/IProject'
|
import type {IProject} from '@/modelTypes/IProject'
|
||||||
|
|
||||||
const props = defineProps({
|
const {
|
||||||
projectId: {
|
projectId,
|
||||||
type: Number as PropType<IProject['id']>,
|
} = defineProps<{
|
||||||
required: true,
|
projectId: IProject['id'],
|
||||||
},
|
}>()
|
||||||
})
|
|
||||||
|
|
||||||
const ctaVisible = ref(false)
|
const ctaVisible = ref(false)
|
||||||
const showTaskSearch = ref(false)
|
const showTaskSearch = ref(false)
|
||||||
@ -169,7 +168,7 @@ const {
|
|||||||
searchTerm,
|
searchTerm,
|
||||||
params,
|
params,
|
||||||
sortByParam,
|
sortByParam,
|
||||||
} = useTaskList(toRef(props, 'projectId'), {position: 'asc' })
|
} = useTaskList(projectId, {position: 'asc' })
|
||||||
|
|
||||||
|
|
||||||
const isAlphabeticalSorting = computed(() => {
|
const isAlphabeticalSorting = computed(() => {
|
||||||
|
@ -180,7 +180,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {toRef, computed, type Ref} from 'vue'
|
import {computed, type Ref} from 'vue'
|
||||||
|
|
||||||
import {useStorage} from '@vueuse/core'
|
import {useStorage} from '@vueuse/core'
|
||||||
|
|
||||||
@ -200,6 +200,7 @@ import {useTaskList} from '@/composables/useTaskList'
|
|||||||
|
|
||||||
import type {SortBy} from '@/composables/useTaskList'
|
import type {SortBy} from '@/composables/useTaskList'
|
||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
import type {IProject} from '@/modelTypes/IProject'
|
||||||
|
|
||||||
const ACTIVE_COLUMNS_DEFAULT = {
|
const ACTIVE_COLUMNS_DEFAULT = {
|
||||||
index: true,
|
index: true,
|
||||||
@ -217,12 +218,11 @@ const ACTIVE_COLUMNS_DEFAULT = {
|
|||||||
createdBy: false,
|
createdBy: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps({
|
const {
|
||||||
projectId: {
|
projectId,
|
||||||
type: Number,
|
} = defineProps<{
|
||||||
required: true,
|
projectId: IProject['id'],
|
||||||
},
|
}>()
|
||||||
})
|
|
||||||
|
|
||||||
const SORT_BY_DEFAULT: SortBy = {
|
const SORT_BY_DEFAULT: SortBy = {
|
||||||
index: 'desc',
|
index: 'desc',
|
||||||
@ -231,7 +231,7 @@ const SORT_BY_DEFAULT: SortBy = {
|
|||||||
const activeColumns = useStorage('tableViewColumns', {...ACTIVE_COLUMNS_DEFAULT})
|
const activeColumns = useStorage('tableViewColumns', {...ACTIVE_COLUMNS_DEFAULT})
|
||||||
const sortBy = useStorage<SortBy>('tableViewSortBy', {...SORT_BY_DEFAULT})
|
const sortBy = useStorage<SortBy>('tableViewSortBy', {...SORT_BY_DEFAULT})
|
||||||
|
|
||||||
const taskList = useTaskList(toRef(props, 'projectId'), sortBy.value)
|
const taskList = useTaskList(projectId, sortBy.value)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
loading,
|
loading,
|
||||||
|
@ -447,7 +447,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {ref, reactive, toRef, shallowReactive, computed, watch, watchEffect, nextTick, type PropType} from 'vue'
|
import {ref, reactive, toRef, shallowReactive, computed, watch, watchEffect, nextTick} from 'vue'
|
||||||
import {useRouter, type RouteLocation} from 'vue-router'
|
import {useRouter, type RouteLocation} from 'vue-router'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import {unrefElement} from '@vueuse/core'
|
import {unrefElement} from '@vueuse/core'
|
||||||
@ -500,15 +500,13 @@ import type {Action as MessageAction} from '@/message'
|
|||||||
import {useProjectStore} from '@/stores/projects'
|
import {useProjectStore} from '@/stores/projects'
|
||||||
import {TASK_REPEAT_MODES} from '@/types/IRepeatMode'
|
import {TASK_REPEAT_MODES} from '@/types/IRepeatMode'
|
||||||
|
|
||||||
const props = defineProps({
|
const {
|
||||||
taskId: {
|
taskId,
|
||||||
type: Number as PropType<ITask['id']>,
|
backdropView,
|
||||||
required: true,
|
} = defineProps<{
|
||||||
},
|
taskId: ITask['id'],
|
||||||
backdropView: {
|
backdropView?: RouteLocation['fullPath'],
|
||||||
type: String as PropType<RouteLocation['fullPath']>,
|
}>()
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
defineEmits(['close'])
|
defineEmits(['close'])
|
||||||
|
|
||||||
@ -535,8 +533,6 @@ const taskColor = ref<ITask['hexColor']>('')
|
|||||||
// Used to avoid flashing of empty elements if the task content is not yet loaded.
|
// Used to avoid flashing of empty elements if the task content is not yet loaded.
|
||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
|
|
||||||
const taskId = toRef(props, 'taskId')
|
|
||||||
|
|
||||||
const project = computed(() => projectStore.projects[task.value.projectId])
|
const project = computed(() => projectStore.projects[task.value.projectId])
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (typeof project.value === 'undefined') {
|
if (typeof project.value === 'undefined') {
|
||||||
@ -567,13 +563,14 @@ const color = computed(() => {
|
|||||||
|
|
||||||
const hasAttachments = computed(() => attachmentStore.attachments.length > 0)
|
const hasAttachments = computed(() => attachmentStore.attachments.length > 0)
|
||||||
|
|
||||||
const isModal = computed(() => Boolean(props.backdropView))
|
const isModal = computed(() => Boolean(backdropView))
|
||||||
|
|
||||||
function attachmentUpload(file: File, onSuccess?: (url: string) => void) {
|
function attachmentUpload(file: File, onSuccess?: (url: string) => void) {
|
||||||
return uploadFile(taskId.value, file, onSuccess)
|
return uploadFile(taskId, file, onSuccess)
|
||||||
}
|
}
|
||||||
|
|
||||||
const heading = ref<HTMLElement | null>(null)
|
const heading = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
async function scrollToHeading() {
|
async function scrollToHeading() {
|
||||||
scrollIntoView(unrefElement(heading))
|
scrollIntoView(unrefElement(heading))
|
||||||
}
|
}
|
||||||
@ -581,7 +578,9 @@ async function scrollToHeading() {
|
|||||||
const taskService = shallowReactive(new TaskService())
|
const taskService = shallowReactive(new TaskService())
|
||||||
|
|
||||||
// load task
|
// load task
|
||||||
watch(taskId, async (id) => {
|
watch(
|
||||||
|
() => taskId,
|
||||||
|
async (id) => {
|
||||||
if (id === undefined) {
|
if (id === undefined) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -596,7 +595,7 @@ watch(taskId, async (id) => {
|
|||||||
scrollToHeading()
|
scrollToHeading()
|
||||||
visible.value = true
|
visible.value = true
|
||||||
}
|
}
|
||||||
}, {immediate: true})
|
}, {immediate: true})
|
||||||
|
|
||||||
type FieldType =
|
type FieldType =
|
||||||
| 'assignees'
|
| 'assignees'
|
||||||
@ -613,7 +612,7 @@ type FieldType =
|
|||||||
| 'repeatAfter'
|
| 'repeatAfter'
|
||||||
| 'startDate'
|
| 'startDate'
|
||||||
|
|
||||||
const activeFields : {[type in FieldType]: boolean} = reactive({
|
const activeFields: { [type in FieldType]: boolean } = reactive({
|
||||||
assignees: false,
|
assignees: false,
|
||||||
attachments: false,
|
attachments: false,
|
||||||
color: false,
|
color: false,
|
||||||
@ -648,7 +647,7 @@ function setActiveFields() {
|
|||||||
activeFields.startDate = task.value.startDate !== null
|
activeFields.startDate = task.value.startDate !== null
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeFieldElements : {[id in FieldType]: HTMLElement | null} = reactive({
|
const activeFieldElements: { [id in FieldType]: HTMLElement | null } = reactive({
|
||||||
assignees: null,
|
assignees: null,
|
||||||
attachments: null,
|
attachments: null,
|
||||||
color: null,
|
color: null,
|
||||||
@ -723,6 +722,7 @@ async function saveTask(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const showDeleteModal = ref(false)
|
const showDeleteModal = ref(false)
|
||||||
|
|
||||||
async function deleteTask() {
|
async function deleteTask() {
|
||||||
await taskStore.delete(task.value)
|
await taskStore.delete(task.value)
|
||||||
success({message: t('task.detail.deleteSuccess')})
|
success({message: t('task.detail.deleteSuccess')})
|
||||||
@ -837,6 +837,7 @@ h3 .button {
|
|||||||
.icon.is-grey {
|
.icon.is-grey {
|
||||||
color: var(--grey-400);
|
color: var(--grey-400);
|
||||||
}
|
}
|
||||||
|
|
||||||
.date-input {
|
.date-input {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -121,6 +121,9 @@ export default defineConfig(({mode}) => {
|
|||||||
plugins: [
|
plugins: [
|
||||||
vue({
|
vue({
|
||||||
reactivityTransform: true,
|
reactivityTransform: true,
|
||||||
|
script: {
|
||||||
|
propsDestructure: true,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
legacy,
|
legacy,
|
||||||
svgLoader({
|
svgLoader({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user