fix: implemented list group view in lead & deal

This commit is contained in:
Shariq Ansari 2024-05-31 18:12:26 +05:30
parent c86e78267d
commit ed47d87315
6 changed files with 359 additions and 256 deletions

@ -1 +1 @@
Subproject commit 1394a12b6de105649c8ca5beeead62a38ef1b18e Subproject commit 90c75affe85b2a1abfce68d61c0c5043f093a8a0

View File

@ -29,14 +29,7 @@
</Button> </Button>
</ListHeaderItem> </ListHeaderItem>
</ListHeader> </ListHeader>
<ListRows id="list-rows"> <ListRows :rows="rows" v-slot="{ idx, column, item }">
<ListRow
class="mx-5"
v-for="row in rows"
:key="row.name"
v-slot="{ idx, column, item }"
:row="row"
>
<div v-if="column.key === '_assign'" class="flex items-center"> <div v-if="column.key === '_assign'" class="flex items-center">
<MultipleAvatar <MultipleAvatar
:avatars="item" :avatars="item"
@ -85,8 +78,7 @@
variant="ghosted" variant="ghosted"
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'" :class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
@click.stop.prevent=" @click.stop.prevent="
() => () => emit('likeDoc', { name: row.name, liked: isLiked(item) })
emit('likeDoc', { name: row.name, liked: isLiked(item) })
" "
> >
<HeartIcon class="h-4 w-4" /> <HeartIcon class="h-4 w-4" />
@ -168,7 +160,6 @@
</div> </div>
</template> </template>
</ListRowItem> </ListRowItem>
</ListRow>
</ListRows> </ListRows>
<ListSelectBanner> <ListSelectBanner>
<template #actions="{ selections, unselectAll }"> <template #actions="{ selections, unselectAll }">
@ -199,13 +190,12 @@ import MultipleAvatar from '@/components/MultipleAvatar.vue'
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue' import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
import PhoneIcon from '@/components/Icons/PhoneIcon.vue' import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
import ListBulkActions from '@/components/ListBulkActions.vue' import ListBulkActions from '@/components/ListBulkActions.vue'
import ListRows from '@/components/ListViews/ListRows.vue'
import { import {
Avatar, Avatar,
ListView, ListView,
ListHeader, ListHeader,
ListHeaderItem, ListHeaderItem,
ListRows,
ListRow,
ListRowItem, ListRowItem,
ListSelectBanner, ListSelectBanner,
ListFooter, ListFooter,

View File

@ -29,14 +29,7 @@
</Button> </Button>
</ListHeaderItem> </ListHeaderItem>
</ListHeader> </ListHeader>
<ListRows id="list-rows"> <ListRows :rows="rows" v-slot="{ idx, column, item }">
<ListRow
class="mx-5"
v-for="row in rows"
:key="row.name"
v-slot="{ idx, column, item }"
:row="row"
>
<div v-if="column.key === '_assign'" class="flex items-center"> <div v-if="column.key === '_assign'" class="flex items-center">
<MultipleAvatar <MultipleAvatar
:avatars="item" :avatars="item"
@ -123,7 +116,10 @@
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'" :class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
@click.stop.prevent=" @click.stop.prevent="
() => () =>
emit('likeDoc', { name: row.name, liked: isLiked(item) }) emit('likeDoc', {
name: row.name,
liked: isLiked(item),
})
" "
> >
<HeartIcon class="h-4 w-4" /> <HeartIcon class="h-4 w-4" />
@ -177,7 +173,6 @@
</div> </div>
</template> </template>
</ListRowItem> </ListRowItem>
</ListRow>
</ListRows> </ListRows>
<ListSelectBanner> <ListSelectBanner>
<template #actions="{ selections, unselectAll }"> <template #actions="{ selections, unselectAll }">
@ -208,13 +203,12 @@ import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
import PhoneIcon from '@/components/Icons/PhoneIcon.vue' import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
import MultipleAvatar from '@/components/MultipleAvatar.vue' import MultipleAvatar from '@/components/MultipleAvatar.vue'
import ListBulkActions from '@/components/ListBulkActions.vue' import ListBulkActions from '@/components/ListBulkActions.vue'
import ListRows from '@/components/ListViews/ListRows.vue'
import { import {
Avatar, Avatar,
ListView, ListView,
ListHeader, ListHeader,
ListHeaderItem, ListHeaderItem,
ListRows,
ListRow,
ListSelectBanner, ListSelectBanner,
ListRowItem, ListRowItem,
ListFooter, ListFooter,

View File

@ -0,0 +1,64 @@
<template>
<div class="mx-5 mt-2 h-full overflow-y-auto" v-if="showGroupedRows">
<div v-for="group in reactivieRows" :key="group.group">
<ListGroupHeader :group="group">
<div
class="my-2 flex items-center gap-2 text-base font-medium text-gray-800"
>
<div>{{ __('Status') }} -</div>
<div class="flex items-center gap-1">
<IndicatorIcon :class="group.color" />
<div>{{ group.group }}</div>
</div>
</div>
</ListGroupHeader>
<ListGroupRows :group="group" id="list-rows">
<ListRow
v-for="row in group.rows"
:key="row.name"
v-slot="{ idx, column, item }"
:row="row"
>
<slot v-bind="{ idx, column, item }" />
</ListRow>
</ListGroupRows>
</div>
</div>
<ListRows class="mx-5" v-else id="list-rows">
<ListRow
v-for="row in reactivieRows"
:key="row.name"
v-slot="{ idx, column, item }"
:row="row"
>
<slot v-bind="{ idx, column, item }" />
</ListRow>
</ListRows>
</template>
<script setup>
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
import { ListRows, ListRow, ListGroupHeader, ListGroupRows } from 'frappe-ui'
import { ref, computed, watch } from 'vue'
const props = defineProps({
rows: {
type: Array,
required: true,
},
})
const reactivieRows = ref(props.rows)
watch(
() => props.rows,
(val) => (reactivieRows.value = val)
)
let showGroupedRows = computed(() => {
return props.rows.every(
(row) => row.group && row.rows && Array.isArray(row.rows)
)
})
</script>

View File

@ -77,6 +77,7 @@ import {
formatTime, formatTime,
} from '@/utils' } from '@/utils'
import { Breadcrumbs } from 'frappe-ui' import { Breadcrumbs } from 'frappe-ui'
import { useRoute } from 'vue-router'
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
const breadcrumbs = [{ label: __('Deals'), route: { name: 'Deals' } }] const breadcrumbs = [{ label: __('Deals'), route: { name: 'Deals' } }]
@ -85,6 +86,8 @@ const { getUser } = usersStore()
const { getOrganization } = organizationsStore() const { getOrganization } = organizationsStore()
const { getDealStatus } = statusesStore() const { getDealStatus } = statusesStore()
const route = useRoute()
const dealsListView = ref(null) const dealsListView = ref(null)
const showDealModal = ref(false) const showDealModal = ref(false)
@ -98,7 +101,7 @@ const viewControls = ref(null)
// Rows // Rows
const rows = computed(() => { const rows = computed(() => {
if (!deals.value?.data?.data) return [] if (!deals.value?.data?.data) return []
return deals.value.data.data.map((deal) => { let listRows = deals.value.data.data.map((deal) => {
let _rows = {} let _rows = {}
deals.value.data.rows.forEach((row) => { deals.value.data.rows.forEach((row) => {
_rows[row] = deal[row] _rows[row] = deal[row]
@ -174,5 +177,31 @@ const rows = computed(() => {
}) })
return _rows return _rows
}) })
if (route.params.viewType === 'group_by') {
return getGroupedByRows(listRows)
}
return listRows
}) })
function getGroupedByRows(listRows) {
let groupedRows = []
listRows.forEach((row) => {
if (!groupedRows.some((group) => group.group === row.status.label)) {
groupedRows.push({
group: row.status.label,
color: getDealStatus(row.status.label)?.iconColorClass,
collapsed: false,
rows: [],
})
}
groupedRows.filter((group) => {
if (group.group === row.status.label) {
group.rows.push(row)
}
})
})
return groupedRows || listRows
}
</script> </script>

View File

@ -78,7 +78,7 @@ import {
createToast, createToast,
} from '@/utils' } from '@/utils'
import { createResource, Breadcrumbs } from 'frappe-ui' import { createResource, Breadcrumbs } from 'frappe-ui'
import { useRouter } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import { ref, computed, reactive } from 'vue' import { ref, computed, reactive } from 'vue'
const breadcrumbs = [{ label: __('Leads'), route: { name: 'Leads' } }] const breadcrumbs = [{ label: __('Leads'), route: { name: 'Leads' } }]
@ -88,6 +88,7 @@ const { getOrganization } = organizationsStore()
const { getLeadStatus } = statusesStore() const { getLeadStatus } = statusesStore()
const router = useRouter() const router = useRouter()
const route = useRoute()
const leadsListView = ref(null) const leadsListView = ref(null)
const showLeadModal = ref(false) const showLeadModal = ref(false)
@ -102,7 +103,7 @@ const viewControls = ref(null)
// Rows // Rows
const rows = computed(() => { const rows = computed(() => {
if (!leads.value?.data?.data) return [] if (!leads.value?.data?.data) return []
return leads.value?.data.data.map((lead) => { let listRows = leads.value?.data.data.map((lead) => {
let _rows = {} let _rows = {}
leads.value?.data.rows.forEach((row) => { leads.value?.data.rows.forEach((row) => {
_rows[row] = lead[row] _rows[row] = lead[row]
@ -182,8 +183,33 @@ const rows = computed(() => {
}) })
return _rows return _rows
}) })
if (route.params.viewType === 'group_by') {
return getGroupedByRows(listRows)
}
return listRows
}) })
function getGroupedByRows(listRows) {
let groupedRows = []
listRows.forEach((row) => {
if (!groupedRows.some((group) => group.group === row.status.label)) {
groupedRows.push({
group: row.status.label,
color: getLeadStatus(row.status.label)?.iconColorClass,
collapsed: false,
rows: [],
})
}
groupedRows.filter((group) => {
if (group.group === row.status.label) {
group.rows.push(row)
}
})
})
return groupedRows || listRows
}
let newLead = reactive({ let newLead = reactive({
salutation: '', salutation: '',
first_name: '', first_name: '',