Merge pull request #197 from frappe/develop
chore: Merge develop to main
This commit is contained in:
commit
f6ccfc8ae6
@ -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:
|
||||
|
||||
@ -108,8 +108,8 @@ class CRMDeal(Document):
|
||||
"""
|
||||
sla = get_sla(self)
|
||||
if not sla:
|
||||
# self.first_responded_on = None
|
||||
# self.first_response_time = None
|
||||
self.first_responded_on = None
|
||||
self.first_response_time = None
|
||||
return
|
||||
self.sla = sla.name
|
||||
|
||||
|
||||
@ -234,8 +234,8 @@ class CRMLead(Document):
|
||||
"""
|
||||
sla = get_sla(self)
|
||||
if not sla:
|
||||
# self.first_responded_on = None
|
||||
# self.first_response_time = None
|
||||
self.first_responded_on = None
|
||||
self.first_response_time = None
|
||||
return
|
||||
self.sla = sla.name
|
||||
|
||||
|
||||
32
docker/docker-compose.yml
Normal file
32
docker/docker-compose.yml
Normal file
@ -0,0 +1,32 @@
|
||||
version: "3.7"
|
||||
name: crm
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb:10.6
|
||||
command:
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
- --skip-character-set-client-handshake
|
||||
- --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: 123
|
||||
volumes:
|
||||
- mariadb-data:/var/lib/mysql
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
|
||||
frappe:
|
||||
image: frappe/bench:latest
|
||||
command: bash /workspace/init.sh
|
||||
environment:
|
||||
- SHELL=/bin/bash
|
||||
working_dir: /home/frappe
|
||||
volumes:
|
||||
- .:/workspace
|
||||
ports:
|
||||
- 8000:8000
|
||||
- 9000:9000
|
||||
|
||||
volumes:
|
||||
mariadb-data:
|
||||
40
docker/init.sh
Normal file
40
docker/init.sh
Normal file
@ -0,0 +1,40 @@
|
||||
#!bin/bash
|
||||
|
||||
if [ -d "/home/frappe/frappe-bench/apps/frappe" ]; then
|
||||
echo "Bench already exists, skipping init"
|
||||
cd frappe-bench
|
||||
bench start
|
||||
else
|
||||
echo "Creating new bench..."
|
||||
fi
|
||||
|
||||
bench init --skip-redis-config-generation frappe-bench
|
||||
|
||||
cd frappe-bench
|
||||
|
||||
# Use containers instead of localhost
|
||||
bench set-mariadb-host mariadb
|
||||
bench set-redis-cache-host redis:6379
|
||||
bench set-redis-queue-host redis:6379
|
||||
bench set-redis-socketio-host redis:6379
|
||||
|
||||
# Remove redis, watch from Procfile
|
||||
sed -i '/redis/d' ./Procfile
|
||||
sed -i '/watch/d' ./Procfile
|
||||
|
||||
bench get-app crm
|
||||
|
||||
bench new-site crm.localhost \
|
||||
--force \
|
||||
--mariadb-root-password 123 \
|
||||
--admin-password admin \
|
||||
--no-mariadb-socket
|
||||
|
||||
bench --site crm.localhost install-app crm
|
||||
bench --site crm.localhost set-config developer_mode 1
|
||||
bench --site crm.localhost clear-cache
|
||||
bench --site crm.localhost set-config mute_emails 1
|
||||
bench --site crm.localhost add-user alex@example.com --first-name Alex --last-name Scott --password 123 --user-type 'System User' --add-role 'crm Admin'
|
||||
bench use crm.localhost
|
||||
|
||||
bench start
|
||||
@ -1 +1 @@
|
||||
Subproject commit 38a7784d7be13493e975a9def90a28b1f5cda095
|
||||
Subproject commit 1394a12b6de105649c8ca5beeead62a38ef1b18e
|
||||
@ -13,7 +13,7 @@
|
||||
"@vueuse/core": "^10.3.0",
|
||||
"@vueuse/integrations": "^10.3.0",
|
||||
"feather-icons": "^4.28.0",
|
||||
"frappe-ui": "^0.1.53",
|
||||
"frappe-ui": "^0.1.55",
|
||||
"gemoji": "^8.1.0",
|
||||
"mime": "^4.0.1",
|
||||
"pinia": "^2.0.33",
|
||||
|
||||
@ -950,6 +950,10 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: 'CRM Lead',
|
||||
},
|
||||
tabs: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const doc = defineModel()
|
||||
@ -1078,7 +1082,7 @@ const defaultActions = computed(() => {
|
||||
{
|
||||
icon: h(WhatsAppIcon, { class: 'h-4 w-4' }),
|
||||
label: __('New WhatsApp Message'),
|
||||
onClick: () => (tabIndex.value = 5),
|
||||
onClick: () => (tabIndex.value = getTabIndex('WhatsApp')),
|
||||
condition: () => whatsappEnabled.value,
|
||||
},
|
||||
]
|
||||
@ -1354,6 +1358,10 @@ function scroll(hash) {
|
||||
}, 500)
|
||||
}
|
||||
|
||||
function getTabIndex(name) {
|
||||
return props.tabs.findIndex((tab) => tab.name === name)
|
||||
}
|
||||
|
||||
defineExpose({ emailBox })
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
@ -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...')
|
||||
|
||||
18
frontend/src/components/Icons/HeartIcon.vue
Normal file
18
frontend/src/components/Icons/HeartIcon.vue
Normal 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>
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
ref="activities"
|
||||
doctype="CRM Lead"
|
||||
:title="tab.name"
|
||||
:tabs="tabs"
|
||||
v-model:reload="reload"
|
||||
v-model:tabIndex="tabIndex"
|
||||
v-model="lead"
|
||||
@ -304,13 +305,14 @@ import {
|
||||
Breadcrumbs,
|
||||
call,
|
||||
} from 'frappe-ui'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ref, computed, onMounted, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const { $dialog, makeCall } = globalStore()
|
||||
const { getContactByName, contacts } = contactsStore()
|
||||
const { organizations } = organizationsStore()
|
||||
const { statusOptions, getLeadStatus } = statusesStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const props = defineProps({
|
||||
@ -449,6 +451,17 @@ const tabs = computed(() => {
|
||||
return tabOptions.filter((tab) => (tab.condition ? tab.condition() : true))
|
||||
})
|
||||
|
||||
watch(tabs, (value) => {
|
||||
if (value && route.params.tabName) {
|
||||
let index = value.findIndex(
|
||||
(tab) => tab.name.toLowerCase() === route.params.tabName.toLowerCase()
|
||||
)
|
||||
if (index !== -1) {
|
||||
tabIndex.value = index
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function validateFile(file) {
|
||||
let extn = file.name.split('.').pop().toLowerCase()
|
||||
if (!['png', 'jpg', 'jpeg'].includes(extn)) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -15,7 +15,7 @@ const routes = [
|
||||
meta: { scrollPos: { top: 0, left: 0 } },
|
||||
},
|
||||
{
|
||||
path: '/leads/:leadId',
|
||||
path: '/leads/:leadId/:tabName?',
|
||||
name: 'Lead',
|
||||
component: () => import('@/pages/Lead.vue'),
|
||||
props: true,
|
||||
@ -27,7 +27,7 @@ const routes = [
|
||||
meta: { scrollPos: { top: 0, left: 0 } },
|
||||
},
|
||||
{
|
||||
path: '/deals/:dealId',
|
||||
path: '/deals/:dealId/:tabName?',
|
||||
name: 'Deal',
|
||||
component: () => import('@/pages/Deal.vue'),
|
||||
props: true,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user