fix: added custom renderers for Lead/Deal/Task fields using slots for column title & kanban fields
This commit is contained in:
parent
d469a84f46
commit
d8252cae19
@ -85,25 +85,40 @@
|
|||||||
: undefined,
|
: undefined,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="h-5 flex items-center">
|
<slot
|
||||||
<div v-if="fields[titleField]">{{ fields[titleField] }}</div>
|
name="item-title"
|
||||||
<div class="text-gray-500" v-else>{{ __('No Title') }}</div>
|
v-bind="{ fields, titleField, itemName: fields.name }"
|
||||||
</div>
|
>
|
||||||
<div class="border-b h-px my-2.5" />
|
<div class="h-5 flex items-center">
|
||||||
<div class="flex flex-col gap-2">
|
<div v-if="fields[titleField]">{{ fields[titleField] }}</div>
|
||||||
<div v-for="value in column.fields" :key="value">
|
<div class="text-gray-500" v-else>{{ __('No Title') }}</div>
|
||||||
<div class="truncate">{{ fields[value] || '-' }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</slot>
|
||||||
|
<div class="border-b h-px my-2.5" />
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-3.5">
|
||||||
|
<template v-for="value in column.fields" :key="value">
|
||||||
|
<slot
|
||||||
|
name="item-fields"
|
||||||
|
v-bind="{
|
||||||
|
fields,
|
||||||
|
fieldName: value,
|
||||||
|
itemName: fields.name,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div v-if="fields[value]" class="truncate">
|
||||||
|
{{ fields[value] }}
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-b h-px mt-2.5 mb-2" />
|
<div class="border-b h-px mt-2.5 mb-2" />
|
||||||
<div class="flex gap-2 items-center justify-between">
|
<slot name="item-actions">
|
||||||
<div></div>
|
<div class="flex gap-2 items-center justify-between">
|
||||||
<Button
|
<div></div>
|
||||||
icon="plus"
|
<Button icon="plus" variant="ghost" @click.stop.prevent />
|
||||||
variant="ghost"
|
</div>
|
||||||
@click.stop.prevent
|
</slot>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</component>
|
</component>
|
||||||
</template>
|
</template>
|
||||||
</Draggable>
|
</Draggable>
|
||||||
|
|||||||
@ -36,7 +36,129 @@
|
|||||||
onNewClick: (column) => onNewClick(column),
|
onNewClick: (column) => onNewClick(column),
|
||||||
}"
|
}"
|
||||||
@update="(data) => viewControls.updateKanbanSettings(data)"
|
@update="(data) => viewControls.updateKanbanSettings(data)"
|
||||||
/>
|
>
|
||||||
|
<template #item-title="{ titleField, itemName }">
|
||||||
|
<div class="flex gap-2 items-center">
|
||||||
|
<div v-if="titleField === 'status'">
|
||||||
|
<IndicatorIcon :class="getRow(itemName, titleField).color" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="
|
||||||
|
titleField === 'organization' && getRow(itemName, titleField).label
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, titleField).logo"
|
||||||
|
:label="getRow(itemName, titleField).label"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="
|
||||||
|
titleField === 'deal_owner' &&
|
||||||
|
getRow(itemName, titleField).full_name
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, titleField).user_image"
|
||||||
|
:label="getRow(itemName, titleField).full_name"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
[
|
||||||
|
'modified',
|
||||||
|
'creation',
|
||||||
|
'first_response_time',
|
||||||
|
'first_responded_on',
|
||||||
|
'response_by',
|
||||||
|
].includes(titleField)
|
||||||
|
"
|
||||||
|
class="truncate text-base"
|
||||||
|
>
|
||||||
|
<Tooltip :text="getRow(itemName, titleField).label">
|
||||||
|
<div>{{ getRow(itemName, titleField).timeAgo }}</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="titleField === 'sla_status'" class="truncate text-base">
|
||||||
|
<Badge
|
||||||
|
v-if="getRow(itemName, titleField).value"
|
||||||
|
:variant="'subtle'"
|
||||||
|
:theme="getRow(itemName, titleField).color"
|
||||||
|
size="md"
|
||||||
|
:label="getRow(itemName, titleField).value"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="getRow(itemName, titleField).label"
|
||||||
|
class="truncate text-base"
|
||||||
|
>
|
||||||
|
{{ getRow(itemName, titleField).label }}
|
||||||
|
</div>
|
||||||
|
<div class="text-gray-500" v-else>{{ __('No Title') }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #item-fields="{ fieldName, itemName }">
|
||||||
|
<div
|
||||||
|
v-if="getRow(itemName, fieldName).label"
|
||||||
|
class="truncate flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<div v-if="fieldName === 'status'">
|
||||||
|
<IndicatorIcon :class="getRow(itemName, fieldName).color" />
|
||||||
|
</div>
|
||||||
|
<div v-else-if="fieldName === 'organization'">
|
||||||
|
<Avatar
|
||||||
|
v-if="getRow(itemName, fieldName).label"
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, fieldName).logo"
|
||||||
|
:label="getRow(itemName, fieldName).label"
|
||||||
|
size="xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="fieldName === 'deal_owner'">
|
||||||
|
<Avatar
|
||||||
|
v-if="getRow(itemName, fieldName).full_name"
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, fieldName).user_image"
|
||||||
|
:label="getRow(itemName, fieldName).full_name"
|
||||||
|
size="xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
[
|
||||||
|
'modified',
|
||||||
|
'creation',
|
||||||
|
'first_response_time',
|
||||||
|
'first_responded_on',
|
||||||
|
'response_by',
|
||||||
|
].includes(fieldName)
|
||||||
|
"
|
||||||
|
class="truncate text-base"
|
||||||
|
>
|
||||||
|
<Tooltip :text="getRow(itemName, fieldName).label">
|
||||||
|
<div>{{ getRow(itemName, fieldName).timeAgo }}</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="fieldName === 'sla_status'" class="truncate text-base">
|
||||||
|
<Badge
|
||||||
|
v-if="getRow(itemName, fieldName).value"
|
||||||
|
:variant="'subtle'"
|
||||||
|
:theme="getRow(itemName, fieldName).color"
|
||||||
|
size="md"
|
||||||
|
:label="getRow(itemName, fieldName).value"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else class="truncate text-base">
|
||||||
|
{{ getRow(itemName, fieldName).label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</KanbanView>
|
||||||
<DealsListView
|
<DealsListView
|
||||||
ref="dealsListView"
|
ref="dealsListView"
|
||||||
v-else-if="deals.data && rows.length"
|
v-else-if="deals.data && rows.length"
|
||||||
@ -94,7 +216,7 @@ import {
|
|||||||
formatNumberIntoCurrency,
|
formatNumberIntoCurrency,
|
||||||
formatTime,
|
formatTime,
|
||||||
} from '@/utils'
|
} from '@/utils'
|
||||||
import { Breadcrumbs } from 'frappe-ui'
|
import { Breadcrumbs, Tooltip, Avatar } from 'frappe-ui'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { ref, reactive, computed, h } from 'vue'
|
import { ref, reactive, computed, h } from 'vue'
|
||||||
|
|
||||||
@ -118,6 +240,16 @@ const triggerResize = ref(1)
|
|||||||
const updatedPageCount = ref(20)
|
const updatedPageCount = ref(20)
|
||||||
const viewControls = ref(null)
|
const viewControls = ref(null)
|
||||||
|
|
||||||
|
function getRow(name, field) {
|
||||||
|
function getValue(value) {
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return { label: value }
|
||||||
|
}
|
||||||
|
return getValue(rows.value?.find((row) => row.name == name)[field])
|
||||||
|
}
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
const rows = computed(() => {
|
const rows = computed(() => {
|
||||||
if (!deals.value?.data?.data) return []
|
if (!deals.value?.data?.data) return []
|
||||||
|
|||||||
@ -37,7 +37,163 @@
|
|||||||
onNewClick: (column) => onNewClick(column),
|
onNewClick: (column) => onNewClick(column),
|
||||||
}"
|
}"
|
||||||
@update="(data) => viewControls.updateKanbanSettings(data)"
|
@update="(data) => viewControls.updateKanbanSettings(data)"
|
||||||
/>
|
>
|
||||||
|
<template #item-title="{ titleField, itemName }">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<div v-if="titleField === 'status'">
|
||||||
|
<IndicatorIcon :class="getRow(itemName, titleField).color" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="
|
||||||
|
titleField === 'organization' && getRow(itemName, titleField).label
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, titleField).logo"
|
||||||
|
:label="getRow(itemName, titleField).label"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="
|
||||||
|
titleField === 'lead_name' && getRow(itemName, titleField).label
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, titleField).image"
|
||||||
|
:label="getRow(itemName, titleField).image_label"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="
|
||||||
|
titleField === 'lead_owner' &&
|
||||||
|
getRow(itemName, titleField).full_name
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, titleField).user_image"
|
||||||
|
:label="getRow(itemName, titleField).full_name"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="titleField === 'mobile_no'">
|
||||||
|
<PhoneIcon class="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
[
|
||||||
|
'modified',
|
||||||
|
'creation',
|
||||||
|
'first_response_time',
|
||||||
|
'first_responded_on',
|
||||||
|
'response_by',
|
||||||
|
].includes(titleField)
|
||||||
|
"
|
||||||
|
class="truncate text-base"
|
||||||
|
>
|
||||||
|
<Tooltip :text="getRow(itemName, titleField).label">
|
||||||
|
<div>{{ getRow(itemName, titleField).timeAgo }}</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="titleField === 'sla_status'" class="truncate text-base">
|
||||||
|
<Badge
|
||||||
|
v-if="getRow(itemName, titleField).value"
|
||||||
|
:variant="'subtle'"
|
||||||
|
:theme="getRow(itemName, titleField).color"
|
||||||
|
size="md"
|
||||||
|
:label="getRow(itemName, titleField).value"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="getRow(itemName, titleField).label"
|
||||||
|
class="truncate text-base"
|
||||||
|
>
|
||||||
|
{{ getRow(itemName, titleField).label }}
|
||||||
|
</div>
|
||||||
|
<div class="text-gray-500" v-else>{{ __('No Title') }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #item-fields="{ fieldName, itemName }">
|
||||||
|
<div
|
||||||
|
v-if="getRow(itemName, fieldName).label"
|
||||||
|
class="truncate flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<div v-if="fieldName === 'status'">
|
||||||
|
<IndicatorIcon :class="getRow(itemName, fieldName).color" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="
|
||||||
|
fieldName === 'organization' && getRow(itemName, fieldName).label
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, fieldName).logo"
|
||||||
|
:label="getRow(itemName, fieldName).label"
|
||||||
|
size="xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="fieldName === 'lead_name'">
|
||||||
|
<Avatar
|
||||||
|
v-if="getRow(itemName, fieldName).label"
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, fieldName).image"
|
||||||
|
:label="getRow(itemName, fieldName).image_label"
|
||||||
|
size="xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="fieldName === 'lead_owner'">
|
||||||
|
<Avatar
|
||||||
|
v-if="getRow(itemName, fieldName).full_name"
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, fieldName).user_image"
|
||||||
|
:label="getRow(itemName, fieldName).full_name"
|
||||||
|
size="xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
[
|
||||||
|
'modified',
|
||||||
|
'creation',
|
||||||
|
'first_response_time',
|
||||||
|
'first_responded_on',
|
||||||
|
'response_by',
|
||||||
|
].includes(fieldName)
|
||||||
|
"
|
||||||
|
class="truncate text-base"
|
||||||
|
>
|
||||||
|
<Tooltip :text="getRow(itemName, fieldName).label">
|
||||||
|
<div>{{ getRow(itemName, fieldName).timeAgo }}</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="fieldName === 'sla_status'" class="truncate text-base">
|
||||||
|
<Badge
|
||||||
|
v-if="getRow(itemName, fieldName).value"
|
||||||
|
:variant="'subtle'"
|
||||||
|
:theme="getRow(itemName, fieldName).color"
|
||||||
|
size="md"
|
||||||
|
:label="getRow(itemName, fieldName).value"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="fieldName === 'Check'">
|
||||||
|
<FormControl
|
||||||
|
type="checkbox"
|
||||||
|
:modelValue="getRow(itemName, fieldName)"
|
||||||
|
:disabled="true"
|
||||||
|
class="text-gray-900"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else class="truncate text-base">
|
||||||
|
{{ getRow(itemName, fieldName).label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</KanbanView>
|
||||||
<LeadsListView
|
<LeadsListView
|
||||||
ref="leadsListView"
|
ref="leadsListView"
|
||||||
v-else-if="leads.data && rows.length"
|
v-else-if="leads.data && rows.length"
|
||||||
@ -78,6 +234,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import CustomActions from '@/components/CustomActions.vue'
|
import CustomActions from '@/components/CustomActions.vue'
|
||||||
|
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||||
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
||||||
import LeadsIcon from '@/components/Icons/LeadsIcon.vue'
|
import LeadsIcon from '@/components/Icons/LeadsIcon.vue'
|
||||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||||
@ -89,7 +246,7 @@ import { usersStore } from '@/stores/users'
|
|||||||
import { organizationsStore } from '@/stores/organizations'
|
import { organizationsStore } from '@/stores/organizations'
|
||||||
import { statusesStore } from '@/stores/statuses'
|
import { statusesStore } from '@/stores/statuses'
|
||||||
import { dateFormat, dateTooltipFormat, timeAgo, formatTime } from '@/utils'
|
import { dateFormat, dateTooltipFormat, timeAgo, formatTime } from '@/utils'
|
||||||
import { Breadcrumbs } from 'frappe-ui'
|
import { Breadcrumbs, Avatar, Tooltip } from 'frappe-ui'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { ref, computed, reactive, h } from 'vue'
|
import { ref, computed, reactive, h } from 'vue'
|
||||||
|
|
||||||
@ -113,6 +270,16 @@ const triggerResize = ref(1)
|
|||||||
const updatedPageCount = ref(20)
|
const updatedPageCount = ref(20)
|
||||||
const viewControls = ref(null)
|
const viewControls = ref(null)
|
||||||
|
|
||||||
|
function getRow(name, field) {
|
||||||
|
function getValue(value) {
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return { label: value }
|
||||||
|
}
|
||||||
|
return getValue(rows.value?.find((row) => row.name == name)[field])
|
||||||
|
}
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
const rows = computed(() => {
|
const rows = computed(() => {
|
||||||
if (!leads.value?.data?.data) return []
|
if (!leads.value?.data?.data) return []
|
||||||
|
|||||||
@ -32,7 +32,90 @@
|
|||||||
onNewClick: (column) => createTask(column),
|
onNewClick: (column) => createTask(column),
|
||||||
}"
|
}"
|
||||||
@update="(data) => viewControls.updateKanbanSettings(data)"
|
@update="(data) => viewControls.updateKanbanSettings(data)"
|
||||||
/>
|
>
|
||||||
|
<template #item-title="{ titleField, itemName }">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<div v-if="titleField === 'status'">
|
||||||
|
<TaskStatusIcon :status="getRow(itemName, titleField).label" />
|
||||||
|
</div>
|
||||||
|
<div v-else-if="titleField === 'priority'">
|
||||||
|
<TaskPriorityIcon :priority="getRow(itemName, titleField).label" />
|
||||||
|
</div>
|
||||||
|
<div v-else-if="titleField === 'assigned_to'">
|
||||||
|
<Avatar
|
||||||
|
v-if="getRow(itemName, titleField).full_name"
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, titleField).user_image"
|
||||||
|
:label="getRow(itemName, titleField).full_name"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="['modified', 'creation'].includes(titleField)"
|
||||||
|
class="truncate text-base"
|
||||||
|
>
|
||||||
|
<Tooltip :text="getRow(itemName, titleField).label">
|
||||||
|
<div>{{ getRow(itemName, titleField).timeAgo }}</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="getRow(itemName, titleField).label"
|
||||||
|
class="truncate text-base"
|
||||||
|
>
|
||||||
|
{{ getRow(itemName, titleField).label }}
|
||||||
|
</div>
|
||||||
|
<div class="text-gray-500" v-else>{{ __('No Title') }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #item-fields="{ fieldName, itemName }">
|
||||||
|
<div
|
||||||
|
v-if="getRow(itemName, fieldName).label"
|
||||||
|
class="truncate flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<div v-if="fieldName === 'status'">
|
||||||
|
<TaskStatusIcon
|
||||||
|
class="size-3"
|
||||||
|
:status="getRow(itemName, fieldName).label"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="fieldName === 'priority'">
|
||||||
|
<TaskPriorityIcon :priority="getRow(itemName, fieldName).label" />
|
||||||
|
</div>
|
||||||
|
<div v-else-if="fieldName === 'assigned_to'">
|
||||||
|
<Avatar
|
||||||
|
v-if="getRow(itemName, fieldName).full_name"
|
||||||
|
class="flex items-center"
|
||||||
|
:image="getRow(itemName, fieldName).user_image"
|
||||||
|
:label="getRow(itemName, fieldName).full_name"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="['modified', 'creation'].includes(fieldName)"
|
||||||
|
class="truncate text-base"
|
||||||
|
>
|
||||||
|
<Tooltip :text="getRow(itemName, fieldName).label">
|
||||||
|
<div>{{ getRow(itemName, fieldName).timeAgo }}</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="fieldName == 'description'"
|
||||||
|
class="truncate text-base max-h-44"
|
||||||
|
>
|
||||||
|
<TextEditor
|
||||||
|
v-if="getRow(itemName, fieldName).label"
|
||||||
|
:content="getRow(itemName, fieldName).label"
|
||||||
|
:editable="false"
|
||||||
|
editor-class="!prose-sm max-w-none focus:outline-none"
|
||||||
|
class="flex-1 overflow-hidden"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else class="truncate text-base">
|
||||||
|
{{ getRow(itemName, fieldName).label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</KanbanView>
|
||||||
<TasksListView
|
<TasksListView
|
||||||
ref="tasksListView"
|
ref="tasksListView"
|
||||||
v-else-if="tasks.data && rows.length"
|
v-else-if="tasks.data && rows.length"
|
||||||
@ -75,6 +158,8 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import CustomActions from '@/components/CustomActions.vue'
|
import CustomActions from '@/components/CustomActions.vue'
|
||||||
|
import TaskStatusIcon from '@/components/Icons/TaskStatusIcon.vue'
|
||||||
|
import TaskPriorityIcon from '@/components/Icons/TaskPriorityIcon.vue'
|
||||||
import EmailIcon from '@/components/Icons/EmailIcon.vue'
|
import EmailIcon from '@/components/Icons/EmailIcon.vue'
|
||||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||||
import ViewControls from '@/components/ViewControls.vue'
|
import ViewControls from '@/components/ViewControls.vue'
|
||||||
@ -83,7 +168,7 @@ import KanbanView from '@/components/Kanban/KanbanView.vue'
|
|||||||
import TaskModal from '@/components/Modals/TaskModal.vue'
|
import TaskModal from '@/components/Modals/TaskModal.vue'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { dateFormat, dateTooltipFormat, timeAgo } from '@/utils'
|
import { dateFormat, dateTooltipFormat, timeAgo } from '@/utils'
|
||||||
import { Breadcrumbs } from 'frappe-ui'
|
import { Breadcrumbs, Tooltip, Avatar, TextEditor } from 'frappe-ui'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
const breadcrumbs = [{ label: __('Tasks'), route: { name: 'Tasks' } }]
|
const breadcrumbs = [{ label: __('Tasks'), route: { name: 'Tasks' } }]
|
||||||
@ -99,6 +184,16 @@ const triggerResize = ref(1)
|
|||||||
const updatedPageCount = ref(20)
|
const updatedPageCount = ref(20)
|
||||||
const viewControls = ref(null)
|
const viewControls = ref(null)
|
||||||
|
|
||||||
|
function getRow(name, field) {
|
||||||
|
function getValue(value) {
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return { label: value }
|
||||||
|
}
|
||||||
|
return getValue(rows.value?.find((row) => row.name == name)[field])
|
||||||
|
}
|
||||||
|
|
||||||
const rows = computed(() => {
|
const rows = computed(() => {
|
||||||
if (!tasks.value?.data?.data) return []
|
if (!tasks.value?.data?.data) return []
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user