1
0
forked from test/crm

Merge pull request #196 from shariquerik/liked-by

feat: Liked By in List View
This commit is contained in:
Shariq Ansari 2024-05-22 22:10:04 +05:30 committed by Shariq Ansari
commit 47d47f4c5f
19 changed files with 579 additions and 42 deletions

View File

@ -215,6 +215,9 @@ def get_list_data(
rows.append(column.get("key"))
column["label"] = _(column.get("label"))
if column.get("key") == "_liked_by" and column.get("width") == "10rem":
column["width"] = "50px"
data = frappe.get_list(
doctype,
fields=rows,
@ -248,6 +251,7 @@ def get_list_data(
},
{"label": "Assigned To", "type": "Text", "value": "_assign"},
{"label": "Owner", "type": "Link", "value": "owner", "options": "User"},
{"label": "Liked By", "type": "Data", "value": "_liked_by"},
]
for field in std_fields:

@ -1 +1 @@
Subproject commit 38a7784d7be13493e975a9def90a28b1f5cda095
Subproject commit 5e726bf5ab8cd6f23eaf0f41df48126ba40451a2

View File

@ -189,7 +189,6 @@
<script setup>
import NoteIcon from '@/components/Icons/NoteIcon.vue'
import MinimizeIcon from '@/components/Icons/MinimizeIcon.vue'
import DialpadIcon from '@/components/Icons/DialpadIcon.vue'
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
import CountUpTimer from '@/components/CountUpTimer.vue'
import NoteModal from '@/components/Modals/NoteModal.vue'
@ -201,7 +200,7 @@ import { Avatar, call } from 'frappe-ui'
import { onMounted, ref, watch } from 'vue'
const { getContact, getLeadContact } = contactsStore()
const { setMakeCall, setTwilioEnabled, $dialog } = globalStore()
const { setMakeCall, setTwilioEnabled } = globalStore()
let device = ''
let log = ref('Connecting...')

View File

@ -0,0 +1,18 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="fillCurrent"
stroke="currentColor"
stroke-width="1"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-heart"
>
<path
d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"
/>
</svg>
</template>

View File

@ -10,7 +10,24 @@
}"
row-key="name"
>
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')" />
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')">
<ListHeaderItem
v-for="column in columns"
:key="column.key"
:item="column"
@columnWidthUpdated="emit('columnWidthUpdated', column)"
>
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
class="!h-4"
:class="isLikeFilterApplied ? 'fill-red-500' : 'fill-white'"
@click="() => emit('applyLikeFilter')"
>
<HeartIcon class="h-4 w-4" />
</Button>
</ListHeaderItem>
</ListHeader>
<ListRows id="list-rows">
<ListRow
class="mx-5"
@ -39,7 +56,14 @@
v-if="['modified', 'creation'].includes(column.key)"
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
<Tooltip :text="item.label">
@ -53,7 +77,14 @@
size="md"
:label="__(item.label)"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
/>
</div>
@ -65,11 +96,31 @@
class="text-gray-900"
/>
</div>
<div v-else-if="column.key === '_liked_by'">
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
@click.stop.prevent="
() =>
emit('likeDoc', { name: row.name, liked: isLiked(item) })
"
>
<HeartIcon class="h-4 w-4" />
</Button>
</div>
<div
v-else
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
{{ label }}
@ -108,11 +159,13 @@
/>
</template>
<script setup>
import HeartIcon from '@/components/Icons/HeartIcon.vue'
import ListBulkActions from '@/components/ListBulkActions.vue'
import {
Avatar,
ListView,
ListHeader,
ListHeaderItem,
ListRows,
ListRow,
ListSelectBanner,
@ -121,7 +174,8 @@ import {
Tooltip,
Dropdown,
} from 'frappe-ui'
import { ref, watch } from 'vue'
import { sessionStore } from '@/stores/session'
import { ref, computed, watch } from 'vue'
const props = defineProps({
rows: {
@ -149,11 +203,26 @@ const emit = defineEmits([
'updatePageCount',
'columnWidthUpdated',
'applyFilter',
'applyLikeFilter',
'likeDoc',
])
const pageLengthCount = defineModel()
const list = defineModel('list')
const isLikeFilterApplied = computed(() => {
return list.value.params?.filters?._liked_by ? true : false
})
const { user } = sessionStore()
function isLiked(item) {
if (item) {
let likedByMe = JSON.parse(item)
return likedByMe.includes(user)
}
}
watch(pageLengthCount, (val, old_value) => {
if (val === old_value) return
emit('updatePageCount', val)

View File

@ -14,7 +14,24 @@
}"
row-key="name"
>
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')" />
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')">
<ListHeaderItem
v-for="column in columns"
:key="column.key"
:item="column"
@columnWidthUpdated="emit('columnWidthUpdated', column)"
>
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
class="!h-4"
:class="isLikeFilterApplied ? 'fill-red-500' : 'fill-white'"
@click="() => emit('applyLikeFilter')"
>
<HeartIcon class="h-4 w-4" />
</Button>
</ListHeaderItem>
</ListHeader>
<ListRows id="list-rows">
<ListRow
class="mx-5"
@ -52,7 +69,14 @@
v-if="['modified', 'creation'].includes(column.key)"
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
<Tooltip :text="item.label">
@ -67,11 +91,31 @@
class="text-gray-900"
/>
</div>
<div v-else-if="column.key === '_liked_by'">
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
@click.stop.prevent="
() =>
emit('likeDoc', { name: row.name, liked: isLiked(item) })
"
>
<HeartIcon class="h-4 w-4" />
</Button>
</div>
<div
v-else
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
{{ label }}
@ -110,12 +154,14 @@
/>
</template>
<script setup>
import HeartIcon from '@/components/Icons/HeartIcon.vue'
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
import ListBulkActions from '@/components/ListBulkActions.vue'
import {
Avatar,
ListView,
ListHeader,
ListHeaderItem,
ListRows,
ListRow,
ListSelectBanner,
@ -124,7 +170,8 @@ import {
Tooltip,
Dropdown,
} from 'frappe-ui'
import { ref, watch } from 'vue'
import { sessionStore } from '@/stores/session'
import { ref, computed, watch } from 'vue'
const props = defineProps({
rows: {
@ -152,11 +199,26 @@ const emit = defineEmits([
'updatePageCount',
'columnWidthUpdated',
'applyFilter',
'applyLikeFilter',
'likeDoc',
])
const pageLengthCount = defineModel()
const list = defineModel('list')
const isLikeFilterApplied = computed(() => {
return list.value.params?.filters?._liked_by ? true : false
})
const { user } = sessionStore()
function isLiked(item) {
if (item) {
let likedByMe = JSON.parse(item)
return likedByMe.includes(user)
}
}
watch(pageLengthCount, (val, old_value) => {
if (val === old_value) return
emit('updatePageCount', val)

View File

@ -11,7 +11,24 @@
}"
row-key="name"
>
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')" />
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')">
<ListHeaderItem
v-for="column in columns"
:key="column.key"
:item="column"
@columnWidthUpdated="emit('columnWidthUpdated', column)"
>
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
class="!h-4"
:class="isLikeFilterApplied ? 'fill-red-500' : 'fill-white'"
@click="() => emit('applyLikeFilter')"
>
<HeartIcon class="h-4 w-4" />
</Button>
</ListHeaderItem>
</ListHeader>
<ListRows id="list-rows">
<ListRow
class="mx-5"
@ -25,7 +42,14 @@
:avatars="item"
size="sm"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
/>
</div>
@ -55,6 +79,19 @@
<div v-else-if="column.key === 'mobile_no'">
<PhoneIcon class="h-4 w-4" />
</div>
<div v-else-if="column.key === '_liked_by'">
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
@click.stop.prevent="
() =>
emit('likeDoc', { name: row.name, liked: isLiked(item) })
"
>
<HeartIcon class="h-4 w-4" />
</Button>
</div>
</template>
<template #default="{ label }">
<div
@ -69,7 +106,14 @@
"
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
<Tooltip :text="item.label">
@ -87,7 +131,14 @@
size="md"
:label="item.value"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
/>
</div>
@ -103,7 +154,14 @@
v-else
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
{{ label }}
@ -136,6 +194,7 @@
</template>
<script setup>
import HeartIcon from '@/components/Icons/HeartIcon.vue'
import MultipleAvatar from '@/components/MultipleAvatar.vue'
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
@ -144,6 +203,7 @@ import {
Avatar,
ListView,
ListHeader,
ListHeaderItem,
ListRows,
ListRow,
ListRowItem,
@ -152,7 +212,8 @@ import {
Dropdown,
Tooltip,
} from 'frappe-ui'
import { ref, watch } from 'vue'
import { sessionStore } from '@/stores/session'
import { ref, computed, watch } from 'vue'
const props = defineProps({
rows: {
@ -180,11 +241,26 @@ const emit = defineEmits([
'updatePageCount',
'columnWidthUpdated',
'applyFilter',
'applyLikeFilter',
'likeDoc',
])
const pageLengthCount = defineModel()
const list = defineModel('list')
const isLikeFilterApplied = computed(() => {
return list.value.params?.filters?._liked_by ? true : false
})
const { user } = sessionStore()
function isLiked(item) {
if (item) {
let likedByMe = JSON.parse(item)
return likedByMe.includes(user)
}
}
watch(pageLengthCount, (val, old_value) => {
if (val === old_value) return
emit('updatePageCount', val)

View File

@ -10,7 +10,24 @@
}"
row-key="name"
>
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')" />
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')">
<ListHeaderItem
v-for="column in columns"
:key="column.key"
:item="column"
@columnWidthUpdated="emit('columnWidthUpdated', column)"
>
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
class="!h-4"
:class="isLikeFilterApplied ? 'fill-red-500' : 'fill-white'"
@click="() => emit('applyLikeFilter')"
>
<HeartIcon class="h-4 w-4" />
</Button>
</ListHeaderItem>
</ListHeader>
<ListRows id="list-rows">
<ListRow
class="mx-5"
@ -28,7 +45,14 @@
v-if="['modified', 'creation'].includes(column.key)"
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
<Tooltip :text="item.label">
@ -42,7 +66,14 @@
size="md"
:label="item.label"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
/>
</div>
@ -54,11 +85,31 @@
class="text-gray-900"
/>
</div>
<div v-else-if="column.key === '_liked_by'">
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
@click.stop.prevent="
() =>
emit('likeDoc', { name: row.name, liked: isLiked(item) })
"
>
<HeartIcon class="h-4 w-4" />
</Button>
</div>
<div
v-else
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
{{ label }}
@ -69,7 +120,9 @@
</ListRows>
<ListSelectBanner>
<template #actions="{ selections, unselectAll }">
<Dropdown :options="listBulkActionsRef.bulkActions(selections, unselectAll)">
<Dropdown
:options="listBulkActionsRef.bulkActions(selections, unselectAll)"
>
<Button icon="more-horizontal" variant="ghost" />
</Dropdown>
</template>
@ -94,10 +147,12 @@
/>
</template>
<script setup>
import HeartIcon from '@/components/Icons/HeartIcon.vue'
import ListBulkActions from '@/components/ListBulkActions.vue'
import {
ListView,
ListHeader,
ListHeaderItem,
ListRows,
ListRow,
ListSelectBanner,
@ -106,7 +161,8 @@ import {
Dropdown,
Tooltip,
} from 'frappe-ui'
import { ref, watch } from 'vue'
import { sessionStore } from '@/stores/session'
import { ref, computed, watch } from 'vue'
const props = defineProps({
rows: {
@ -135,11 +191,26 @@ const emit = defineEmits([
'showEmailTemplate',
'columnWidthUpdated',
'applyFilter',
'applyLikeFilter',
'likeDoc',
])
const pageLengthCount = defineModel()
const list = defineModel('list')
const isLikeFilterApplied = computed(() => {
return list.value.params?.filters?._liked_by ? true : false
})
const { user } = sessionStore()
function isLiked(item) {
if (item) {
let likedByMe = JSON.parse(item)
return likedByMe.includes(user)
}
}
watch(pageLengthCount, (val, old_value) => {
if (val === old_value) return
emit('updatePageCount', val)

View File

@ -11,7 +11,24 @@
}"
row-key="name"
>
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')" />
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')">
<ListHeaderItem
v-for="column in columns"
:key="column.key"
:item="column"
@columnWidthUpdated="emit('columnWidthUpdated', column)"
>
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
class="!h-4"
:class="isLikeFilterApplied ? 'fill-red-500' : 'fill-white'"
@click="() => emit('applyLikeFilter')"
>
<HeartIcon class="h-4 w-4" />
</Button>
</ListHeaderItem>
</ListHeader>
<ListRows id="list-rows">
<ListRow
class="mx-5"
@ -25,7 +42,14 @@
:avatars="item"
size="sm"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
/>
</div>
@ -78,13 +102,33 @@
"
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
<Tooltip :text="item.label">
<div>{{ item.timeAgo }}</div>
</Tooltip>
</div>
<div v-else-if="column.key === '_liked_by'">
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
@click.stop.prevent="
() =>
emit('likeDoc', { name: row.name, liked: isLiked(item) })
"
>
<HeartIcon class="h-4 w-4" />
</Button>
</div>
<div
v-else-if="column.key === 'sla_status'"
class="truncate text-base"
@ -96,7 +140,14 @@
size="md"
:label="item.value"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
/>
</div>
@ -112,7 +163,14 @@
v-else
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
{{ label }}
@ -123,7 +181,9 @@
</ListRows>
<ListSelectBanner>
<template #actions="{ selections, unselectAll }">
<Dropdown :options="listBulkActionsRef.bulkActions(selections, unselectAll)">
<Dropdown
:options="listBulkActionsRef.bulkActions(selections, unselectAll)"
>
<Button icon="more-horizontal" variant="ghost" />
</Dropdown>
</template>
@ -143,6 +203,7 @@
</template>
<script setup>
import HeartIcon from '@/components/Icons/HeartIcon.vue'
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
import MultipleAvatar from '@/components/MultipleAvatar.vue'
@ -151,6 +212,7 @@ import {
Avatar,
ListView,
ListHeader,
ListHeaderItem,
ListRows,
ListRow,
ListSelectBanner,
@ -159,7 +221,8 @@ import {
Dropdown,
Tooltip,
} from 'frappe-ui'
import { ref, watch } from 'vue'
import { sessionStore } from '@/stores/session'
import { ref, computed, watch } from 'vue'
const props = defineProps({
rows: {
@ -187,11 +250,26 @@ const emit = defineEmits([
'updatePageCount',
'columnWidthUpdated',
'applyFilter',
'applyLikeFilter',
'likeDoc',
])
const pageLengthCount = defineModel()
const list = defineModel('list')
const isLikeFilterApplied = computed(() => {
return list.value.params?.filters?._liked_by ? true : false
})
const { user } = sessionStore()
function isLiked(item) {
if (item) {
let likedByMe = JSON.parse(item)
return likedByMe.includes(user)
}
}
watch(pageLengthCount, (val, old_value) => {
if (val === old_value) return
emit('updatePageCount', val)

View File

@ -13,7 +13,24 @@
}"
row-key="name"
>
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')" />
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')">
<ListHeaderItem
v-for="column in columns"
:key="column.key"
:item="column"
@columnWidthUpdated="emit('columnWidthUpdated', column)"
>
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
class="!h-4"
:class="isLikeFilterApplied ? 'fill-red-500' : 'fill-white'"
@click="() => emit('applyLikeFilter')"
>
<HeartIcon class="h-4 w-4" />
</Button>
</ListHeaderItem>
</ListHeader>
<ListRows id="list-rows">
<ListRow
class="mx-5"
@ -39,7 +56,14 @@
v-if="['modified', 'creation'].includes(column.key)"
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
<Tooltip :text="item.label">
@ -54,11 +78,31 @@
class="text-gray-900"
/>
</div>
<div v-else-if="column.key === '_liked_by'">
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
@click.stop.prevent="
() =>
emit('likeDoc', { name: row.name, liked: isLiked(item) })
"
>
<HeartIcon class="h-4 w-4" />
</Button>
</div>
<div
v-else
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
{{ label }}
@ -96,11 +140,13 @@
/>
</template>
<script setup>
import HeartIcon from '@/components/Icons/HeartIcon.vue'
import ListBulkActions from '@/components/ListBulkActions.vue'
import {
Avatar,
ListView,
ListHeader,
ListHeaderItem,
ListRows,
ListRow,
ListSelectBanner,
@ -109,7 +155,8 @@ import {
Tooltip,
Dropdown,
} from 'frappe-ui'
import { ref, watch } from 'vue'
import { sessionStore } from '@/stores/session'
import { ref, computed, watch } from 'vue'
const props = defineProps({
rows: {
@ -137,11 +184,26 @@ const emit = defineEmits([
'updatePageCount',
'columnWidthUpdated',
'applyFilter',
'applyLikeFilter',
'likeDoc',
])
const pageLengthCount = defineModel()
const list = defineModel('list')
const isLikeFilterApplied = computed(() => {
return list.value.params?.filters?._liked_by ? true : false
})
const { user } = sessionStore()
function isLiked(item) {
if (item) {
let likedByMe = JSON.parse(item)
return likedByMe.includes(user)
}
}
watch(pageLengthCount, (val, old_value) => {
if (val === old_value) return
emit('updatePageCount', val)

View File

@ -10,7 +10,24 @@
}"
row-key="name"
>
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')" />
<ListHeader class="mx-5" @columnWidthUpdated="emit('columnWidthUpdated')">
<ListHeaderItem
v-for="column in columns"
:key="column.key"
:item="column"
@columnWidthUpdated="emit('columnWidthUpdated', column)"
>
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
class="!h-4"
:class="isLikeFilterApplied ? 'fill-red-500' : 'fill-white'"
@click="() => emit('applyLikeFilter')"
>
<HeartIcon class="h-4 w-4" />
</Button>
</ListHeaderItem>
</ListHeader>
<ListRows id="list-rows">
<ListRow
class="mx-5"
@ -52,7 +69,14 @@
v-if="['modified', 'creation'].includes(column.key)"
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
<Tooltip :text="item.label">
@ -67,11 +91,31 @@
class="text-gray-900"
/>
</div>
<div v-else-if="column.key === '_liked_by'">
<Button
v-if="column.key == '_liked_by'"
variant="ghosted"
:class="isLiked(item) ? 'fill-red-500' : 'fill-white'"
@click.stop.prevent="
() =>
emit('likeDoc', { name: row.name, liked: isLiked(item) })
"
>
<HeartIcon class="h-4 w-4" />
</Button>
</div>
<div
v-else
class="truncate text-base"
@click="
(event) => emit('applyFilter', { event, idx, column, item })
(event) =>
emit('applyFilter', {
event,
idx,
column,
item,
firstColumn: columns[0],
})
"
>
{{ label }}
@ -82,7 +126,9 @@
</ListRows>
<ListSelectBanner>
<template #actions="{ selections, unselectAll }">
<Dropdown :options="listBulkActionsRef.bulkActions(selections, unselectAll)">
<Dropdown
:options="listBulkActionsRef.bulkActions(selections, unselectAll)"
>
<Button icon="more-horizontal" variant="ghost" />
</Dropdown>
</template>
@ -107,6 +153,7 @@
/>
</template>
<script setup>
import HeartIcon from '@/components/Icons/HeartIcon.vue'
import TaskStatusIcon from '@/components/Icons/TaskStatusIcon.vue'
import TaskPriorityIcon from '@/components/Icons/TaskPriorityIcon.vue'
import CalendarIcon from '@/components/Icons/CalendarIcon.vue'
@ -116,6 +163,7 @@ import {
Avatar,
ListView,
ListHeader,
ListHeaderItem,
ListRows,
ListRow,
ListSelectBanner,
@ -124,7 +172,8 @@ import {
Dropdown,
Tooltip,
} from 'frappe-ui'
import { ref, watch } from 'vue'
import { sessionStore } from '@/stores/session'
import { ref, computed, watch } from 'vue'
const props = defineProps({
rows: {
@ -153,11 +202,26 @@ const emit = defineEmits([
'showTask',
'columnWidthUpdated',
'applyFilter',
'applyLikeFilter',
'likeDoc',
])
const pageLengthCount = defineModel()
const list = defineModel('list')
const isLikeFilterApplied = computed(() => {
return list.value.params?.filters?._liked_by ? true : false
})
const { user } = sessionStore()
function isLiked(item) {
if (item) {
let likedByMe = JSON.parse(item)
return likedByMe.includes(user)
}
}
watch(pageLengthCount, (val, old_value) => {
if (val === old_value) return
emit('updatePageCount', val)

View File

@ -748,9 +748,10 @@ function saveView() {
showViewModal.value = true
}
function applyFilter({ event, idx, column, item }) {
function applyFilter({ event, idx, column, item, firstColumn }) {
let restrictedFieldtypes = ['Duration', 'Datetime', 'Time']
if (restrictedFieldtypes.includes(column.type) || idx === 0) return
if (idx === 1 && firstColumn.key == '_liked_by') return
event.stopPropagation()
event.preventDefault()
@ -779,7 +780,26 @@ function applyFilter({ event, idx, column, item }) {
updateFilter(filters)
}
defineExpose({ applyFilter })
function applyLikeFilter() {
let filters = { ...list.value.params.filters }
if (!filters._liked_by) {
filters['_liked_by'] = ['LIKE', '%@me%']
} else {
delete filters['_liked_by']
}
updateFilter(filters)
}
function likeDoc({ name, liked }) {
createResource({
url: 'frappe.desk.like.toggle_like',
params: { doctype: props.doctype, name: name, add: liked ? 'No' : 'Yes' },
auto: true,
onSuccess: () => reload(),
})
}
defineExpose({ applyFilter, applyLikeFilter, likeDoc })
// Watchers
watch(

View File

@ -36,6 +36,8 @@
@columnWidthUpdated="() => triggerResize++"
@updatePageCount="(count) => (updatedPageCount = count)"
@applyFilter="(data) => viewControls.applyFilter(data)"
@applyLikeFilter="(data) => viewControls.applyLikeFilter(data)"
@likeDoc="(data) => viewControls.likeDoc(data)"
/>
<div
v-else-if="callLogs.data"

View File

@ -42,6 +42,8 @@
@columnWidthUpdated="() => triggerResize++"
@updatePageCount="(count) => (updatedPageCount = count)"
@applyFilter="(data) => viewControls.applyFilter(data)"
@applyLikeFilter="(data) => viewControls.applyLikeFilter(data)"
@likeDoc="(data) => viewControls.likeDoc(data)"
/>
<div
v-else-if="contacts.data"

View File

@ -42,6 +42,8 @@
@columnWidthUpdated="() => triggerResize++"
@updatePageCount="(count) => (updatedPageCount = count)"
@applyFilter="(data) => viewControls.applyFilter(data)"
@applyLikeFilter="(data) => viewControls.applyLikeFilter(data)"
@likeDoc="(data) => viewControls.likeDoc(data)"
/>
<div v-else-if="deals.data" class="flex h-full items-center justify-center">
<div

View File

@ -43,6 +43,8 @@
@updatePageCount="(count) => (updatedPageCount = count)"
@showEmailTemplate="showEmailTemplate"
@applyFilter="(data) => viewControls.applyFilter(data)"
@applyLikeFilter="(data) => viewControls.applyLikeFilter(data)"
@likeDoc="(data) => viewControls.likeDoc(data)"
/>
<div
v-else-if="emailTemplates.data"

View File

@ -43,6 +43,8 @@
@columnWidthUpdated="() => triggerResize++"
@updatePageCount="(count) => (updatedPageCount = count)"
@applyFilter="(data) => viewControls.applyFilter(data)"
@applyLikeFilter="(data) => viewControls.applyLikeFilter(data)"
@likeDoc="(data) => viewControls.likeDoc(data)"
/>
<div v-else-if="leads.data" class="flex h-full items-center justify-center">
<div

View File

@ -42,6 +42,8 @@
@columnWidthUpdated="() => triggerResize++"
@updatePageCount="(count) => (updatedPageCount = count)"
@applyFilter="(data) => viewControls.applyFilter(data)"
@applyLikeFilter="(data) => viewControls.applyLikeFilter(data)"
@likeDoc="(data) => viewControls.likeDoc(data)"
/>
<div
v-else-if="organizations.data"

View File

@ -39,6 +39,8 @@
@updatePageCount="(count) => (updatedPageCount = count)"
@showTask="showTask"
@applyFilter="(data) => viewControls.applyFilter(data)"
@applyLikeFilter="(data) => viewControls.applyLikeFilter(data)"
@likeDoc="(data) => viewControls.likeDoc(data)"
/>
<div v-else-if="tasks.data" class="flex h-full items-center justify-center">
<div