Merge branch 'frappe:develop' into translation
This commit is contained in:
commit
3a6514243d
@ -240,7 +240,8 @@ def get_list_data(
|
|||||||
"views": get_views(doctype),
|
"views": get_views(doctype),
|
||||||
"total_count": len(frappe.get_list(doctype, filters=filters)),
|
"total_count": len(frappe.get_list(doctype, filters=filters)),
|
||||||
"row_count": len(data),
|
"row_count": len(data),
|
||||||
"form_script": get_form_script(doctype)
|
"form_script": get_form_script(doctype),
|
||||||
|
"list_script": get_form_script(doctype, "List"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,9 +4,6 @@ from frappe.query_builder import Order
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_notifications():
|
def get_notifications():
|
||||||
if frappe.session.user == "Guest":
|
|
||||||
frappe.throw("Authentication failed", exc=frappe.AuthenticationError)
|
|
||||||
|
|
||||||
Notification = frappe.qb.DocType("CRM Notification")
|
Notification = frappe.qb.DocType("CRM Notification")
|
||||||
query = (
|
query = (
|
||||||
frappe.qb.from_(Notification)
|
frappe.qb.from_(Notification)
|
||||||
@ -46,9 +43,6 @@ def get_notifications():
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def mark_as_read(user=None, comment=None):
|
def mark_as_read(user=None, comment=None):
|
||||||
if frappe.session.user == "Guest":
|
|
||||||
frappe.throw("Authentication failed", exc=frappe.AuthenticationError)
|
|
||||||
|
|
||||||
user = user or frappe.session.user
|
user = user or frappe.session.user
|
||||||
filters = {"to_user": user, "read": False}
|
filters = {"to_user": user, "read": False}
|
||||||
if comment:
|
if comment:
|
||||||
|
|||||||
@ -1,11 +1,8 @@
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist()
|
||||||
def get_users():
|
def get_users():
|
||||||
if frappe.session.user == "Guest":
|
|
||||||
frappe.throw("Authentication failed", exc=frappe.AuthenticationError)
|
|
||||||
|
|
||||||
users = frappe.qb.get_query(
|
users = frappe.qb.get_query(
|
||||||
"User",
|
"User",
|
||||||
fields=["name", "email", "enabled", "user_image", "full_name", "user_type"],
|
fields=["name", "email", "enabled", "user_image", "full_name", "user_type"],
|
||||||
@ -24,9 +21,6 @@ def get_users():
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_contacts():
|
def get_contacts():
|
||||||
if frappe.session.user == "Guest":
|
|
||||||
frappe.throw("Authentication failed", exc=frappe.AuthenticationError)
|
|
||||||
|
|
||||||
contacts = frappe.get_all(
|
contacts = frappe.get_all(
|
||||||
"Contact",
|
"Contact",
|
||||||
fields=[
|
fields=[
|
||||||
@ -66,9 +60,6 @@ def get_contacts():
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_lead_contacts():
|
def get_lead_contacts():
|
||||||
if frappe.session.user == "Guest":
|
|
||||||
frappe.throw("Authentication failed", exc=frappe.AuthenticationError)
|
|
||||||
|
|
||||||
lead_contacts = frappe.get_all(
|
lead_contacts = frappe.get_all(
|
||||||
"CRM Lead",
|
"CRM Lead",
|
||||||
fields=[
|
fields=[
|
||||||
@ -88,9 +79,6 @@ def get_lead_contacts():
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_organizations():
|
def get_organizations():
|
||||||
if frappe.session.user == "Guest":
|
|
||||||
frappe.throw("Authentication failed", exc=frappe.AuthenticationError)
|
|
||||||
|
|
||||||
organizations = frappe.qb.get_query(
|
organizations = frappe.qb.get_query(
|
||||||
"CRM Organization",
|
"CRM Organization",
|
||||||
fields=['*'],
|
fields=['*'],
|
||||||
|
|||||||
@ -4,9 +4,6 @@ from pypika import Criterion
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_views(doctype):
|
def get_views(doctype):
|
||||||
if frappe.session.user == "Guest":
|
|
||||||
frappe.throw("Authentication failed", exc=frappe.AuthenticationError)
|
|
||||||
|
|
||||||
View = frappe.qb.DocType("CRM View Settings")
|
View = frappe.qb.DocType("CRM View Settings")
|
||||||
query = (
|
query = (
|
||||||
frappe.qb.from_(View)
|
frappe.qb.from_(View)
|
||||||
|
|||||||
@ -93,7 +93,7 @@ def get_call_log(name):
|
|||||||
if c:
|
if c:
|
||||||
return [c.full_name, c.image]
|
return [c.full_name, c.image]
|
||||||
return [None, None]
|
return [None, None]
|
||||||
|
|
||||||
def get_lead_contact(number):
|
def get_lead_contact(number):
|
||||||
l = frappe.db.get_value("CRM Lead", {"mobile_no": number, "converted": 0}, ["lead_name", "image"], as_dict=True)
|
l = frappe.db.get_value("CRM Lead", {"mobile_no": number, "converted": 0}, ["lead_name", "image"], as_dict=True)
|
||||||
if l:
|
if l:
|
||||||
|
|||||||
@ -1,8 +1,38 @@
|
|||||||
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
// frappe.ui.form.on("CRM Form Script", {
|
frappe.ui.form.on("CRM Form Script", {
|
||||||
// refresh(frm) {
|
refresh(frm) {
|
||||||
|
frm.set_query("dt", {
|
||||||
|
filters: {
|
||||||
|
istable: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
view(frm) {
|
||||||
|
let has_form_boilerplate = frm.doc.script.includes(
|
||||||
|
"function setupForm("
|
||||||
|
);
|
||||||
|
let has_list_boilerplate = frm.doc.script.includes(
|
||||||
|
"function setupList("
|
||||||
|
);
|
||||||
|
|
||||||
// },
|
if (frm.doc.view == "Form" && !has_form_boilerplate) {
|
||||||
// });
|
frm.doc.script = `
|
||||||
|
function setupForm({ doc }) {
|
||||||
|
return {
|
||||||
|
actions: [],
|
||||||
|
}
|
||||||
|
}`.trim();
|
||||||
|
}
|
||||||
|
if (frm.doc.view == "List" && !has_list_boilerplate) {
|
||||||
|
frm.doc.script = `
|
||||||
|
function setupList({ list }) {
|
||||||
|
return {
|
||||||
|
actions: [],
|
||||||
|
bulk_actions: [],
|
||||||
|
}
|
||||||
|
}`.trim();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"dt",
|
"dt",
|
||||||
|
"view",
|
||||||
"column_break_gboh",
|
"column_break_gboh",
|
||||||
"enabled",
|
"enabled",
|
||||||
"section_break_xeox",
|
"section_break_xeox",
|
||||||
@ -36,16 +37,26 @@
|
|||||||
"label": "Enabled"
|
"label": "Enabled"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "function setupForm({ doc }) {\n return {\n actions: []\n }\n}",
|
"default": "function setupForm({ doc }) {\n return {\n actions: [],\n }\n}",
|
||||||
|
"documentation_url": "https://docs.frappe.io/crm/custom-actions",
|
||||||
"fieldname": "script",
|
"fieldname": "script",
|
||||||
"fieldtype": "Code",
|
"fieldtype": "Code",
|
||||||
"label": "Script",
|
"label": "Script",
|
||||||
"options": "JS"
|
"options": "JS"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "Form",
|
||||||
|
"fieldname": "view",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Apply To",
|
||||||
|
"options": "Form\nList",
|
||||||
|
"set_only_once": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-01-19 21:52:46.078626",
|
"modified": "2024-04-10 18:27:17.617602",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "FCRM",
|
"module": "FCRM",
|
||||||
"name": "CRM Form Script",
|
"name": "CRM Form Script",
|
||||||
|
|||||||
@ -14,6 +14,7 @@ class CRMFormScript(Document):
|
|||||||
if self.dt and self.enabled:
|
if self.dt and self.enabled:
|
||||||
filters = {
|
filters = {
|
||||||
"dt": self.dt,
|
"dt": self.dt,
|
||||||
|
"view": self.view,
|
||||||
"enabled": 1,
|
"enabled": 1,
|
||||||
}
|
}
|
||||||
if self.name:
|
if self.name:
|
||||||
@ -27,13 +28,14 @@ class CRMFormScript(Document):
|
|||||||
frappe.DuplicateEntryError,
|
frappe.DuplicateEntryError,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_form_script(dt):
|
def get_form_script(dt, view="Form"):
|
||||||
"""Returns the script for the given doctype"""
|
"""Returns the form script for the given doctype"""
|
||||||
FormScript = frappe.qb.DocType("CRM Form Script")
|
FormScript = frappe.qb.DocType("CRM Form Script")
|
||||||
query = (
|
query = (
|
||||||
frappe.qb.from_(FormScript)
|
frappe.qb.from_(FormScript)
|
||||||
.select("script")
|
.select("script")
|
||||||
.where(FormScript.dt == dt)
|
.where(FormScript.dt == dt)
|
||||||
|
.where(FormScript.view == view)
|
||||||
.where(FormScript.enabled == 1)
|
.where(FormScript.enabled == 1)
|
||||||
.limit(1)
|
.limit(1)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -327,7 +327,7 @@ function getValSelect(f) {
|
|||||||
if (fieldtype == 'Dynamic Link') {
|
if (fieldtype == 'Dynamic Link') {
|
||||||
return h(FormControl, { type: 'text' })
|
return h(FormControl, { type: 'text' })
|
||||||
}
|
}
|
||||||
return h(Link, { class: 'form-control', doctype: options })
|
return h(Link, { class: 'form-control', doctype: options, value: f.value })
|
||||||
} else if (typeNumber.includes(fieldtype)) {
|
} else if (typeNumber.includes(fieldtype)) {
|
||||||
return h(FormControl, { type: 'number' })
|
return h(FormControl, { type: 'number' })
|
||||||
} else if (typeDate.includes(fieldtype) && operator == 'between') {
|
} else if (typeDate.includes(fieldtype) && operator == 'between') {
|
||||||
@ -437,8 +437,6 @@ function updateOperator(event, filter) {
|
|||||||
|
|
||||||
function isSameTypeOperator(oldOperator, newOperator) {
|
function isSameTypeOperator(oldOperator, newOperator) {
|
||||||
let textOperators = [
|
let textOperators = [
|
||||||
'like',
|
|
||||||
'not like',
|
|
||||||
'equals',
|
'equals',
|
||||||
'not equals',
|
'not equals',
|
||||||
'in',
|
'in',
|
||||||
|
|||||||
@ -103,7 +103,7 @@ import {
|
|||||||
Dropdown,
|
Dropdown,
|
||||||
call,
|
call,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { setupBulkActions, createToast } from '@/utils'
|
import { setupListActions, createToast } from '@/utils'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { onMounted, ref, watch } from 'vue'
|
import { onMounted, ref, watch } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
@ -181,6 +181,7 @@ function deleteValues(selections, unselectAll) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const customBulkActions = ref([])
|
const customBulkActions = ref([])
|
||||||
|
const customListActions = ref([])
|
||||||
|
|
||||||
function bulkActions(selections, unselectAll) {
|
function bulkActions(selections, unselectAll) {
|
||||||
let actions = [
|
let actions = [
|
||||||
@ -209,7 +210,18 @@ function bulkActions(selections, unselectAll) {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!list.value?.data) return
|
if (!list.value?.data) return
|
||||||
setupBulkActions(list.value.data)
|
setupListActions(list.value.data, {
|
||||||
|
list: list.value,
|
||||||
|
call,
|
||||||
|
createToast,
|
||||||
|
$dialog,
|
||||||
|
router,
|
||||||
|
})
|
||||||
customBulkActions.value = list.value?.data?.bulkActions || []
|
customBulkActions.value = list.value?.data?.bulkActions || []
|
||||||
|
customListActions.value = list.value?.data?.listActions || []
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
customListActions,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -103,7 +103,7 @@
|
|||||||
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
||||||
import EditValueModal from '@/components/Modals/EditValueModal.vue'
|
import EditValueModal from '@/components/Modals/EditValueModal.vue'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { createToast } from '@/utils'
|
import { setupListActions, createToast } from '@/utils'
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
ListView,
|
ListView,
|
||||||
@ -117,7 +117,8 @@ import {
|
|||||||
Dropdown,
|
Dropdown,
|
||||||
call,
|
call,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch, onMounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
rows: {
|
rows: {
|
||||||
@ -150,6 +151,8 @@ const emit = defineEmits([
|
|||||||
const pageLengthCount = defineModel()
|
const pageLengthCount = defineModel()
|
||||||
const list = defineModel('list')
|
const list = defineModel('list')
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const { $dialog } = globalStore()
|
const { $dialog } = globalStore()
|
||||||
|
|
||||||
watch(pageLengthCount, (val, old_value) => {
|
watch(pageLengthCount, (val, old_value) => {
|
||||||
@ -199,6 +202,8 @@ function deleteValues(selections, unselectAll) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customListActions = ref([])
|
||||||
|
|
||||||
function bulkActions(selections, unselectAll) {
|
function bulkActions(selections, unselectAll) {
|
||||||
let actions = [
|
let actions = [
|
||||||
{
|
{
|
||||||
@ -212,4 +217,21 @@ function bulkActions(selections, unselectAll) {
|
|||||||
]
|
]
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!list.value?.data) return
|
||||||
|
setupListActions(list.value.data, {
|
||||||
|
list: list.value,
|
||||||
|
call,
|
||||||
|
createToast,
|
||||||
|
$dialog,
|
||||||
|
router,
|
||||||
|
})
|
||||||
|
// customBulkActions.value = list.value?.data?.bulkActions || []
|
||||||
|
customListActions.value = list.value?.data?.listActions || []
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
customListActions,
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -146,7 +146,7 @@ import {
|
|||||||
call,
|
call,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { setupBulkActions, createToast } from '@/utils'
|
import { setupListActions, createToast } from '@/utils'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { onMounted, ref, watch } from 'vue'
|
import { onMounted, ref, watch } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
@ -234,6 +234,7 @@ function deleteValues(selections, unselectAll) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const customBulkActions = ref([])
|
const customBulkActions = ref([])
|
||||||
|
const customListActions = ref([])
|
||||||
|
|
||||||
function bulkActions(selections, unselectAll) {
|
function bulkActions(selections, unselectAll) {
|
||||||
let actions = [
|
let actions = [
|
||||||
@ -266,7 +267,18 @@ function bulkActions(selections, unselectAll) {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!list.value?.data) return
|
if (!list.value?.data) return
|
||||||
setupBulkActions(list.value.data)
|
setupListActions(list.value.data, {
|
||||||
|
list: list.value,
|
||||||
|
call,
|
||||||
|
createToast,
|
||||||
|
$dialog,
|
||||||
|
router,
|
||||||
|
})
|
||||||
customBulkActions.value = list.value?.data?.bulkActions || []
|
customBulkActions.value = list.value?.data?.bulkActions || []
|
||||||
|
customListActions.value = list.value?.data?.listActions || []
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
customListActions,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -85,7 +85,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import EditValueModal from '@/components/Modals/EditValueModal.vue'
|
import EditValueModal from '@/components/Modals/EditValueModal.vue'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { createToast } from '@/utils'
|
import { setupListActions, createToast } from '@/utils'
|
||||||
import {
|
import {
|
||||||
ListView,
|
ListView,
|
||||||
ListHeader,
|
ListHeader,
|
||||||
@ -98,7 +98,8 @@ import {
|
|||||||
call,
|
call,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch, onMounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
rows: {
|
rows: {
|
||||||
@ -132,6 +133,8 @@ const emit = defineEmits([
|
|||||||
const pageLengthCount = defineModel()
|
const pageLengthCount = defineModel()
|
||||||
const list = defineModel('list')
|
const list = defineModel('list')
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const { $dialog } = globalStore()
|
const { $dialog } = globalStore()
|
||||||
|
|
||||||
watch(pageLengthCount, (val, old_value) => {
|
watch(pageLengthCount, (val, old_value) => {
|
||||||
@ -181,6 +184,8 @@ function deleteValues(selections, unselectAll) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customListActions = ref([])
|
||||||
|
|
||||||
function bulkActions(selections, unselectAll) {
|
function bulkActions(selections, unselectAll) {
|
||||||
let actions = [
|
let actions = [
|
||||||
{
|
{
|
||||||
@ -194,4 +199,21 @@ function bulkActions(selections, unselectAll) {
|
|||||||
]
|
]
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!list.value?.data) return
|
||||||
|
setupListActions(list.value.data, {
|
||||||
|
list: list.value,
|
||||||
|
call,
|
||||||
|
createToast,
|
||||||
|
$dialog,
|
||||||
|
router,
|
||||||
|
})
|
||||||
|
// customBulkActions.value = list.value?.data?.bulkActions || []
|
||||||
|
customListActions.value = list.value?.data?.listActions || []
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
customListActions,
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -155,7 +155,7 @@ import {
|
|||||||
call,
|
call,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { setupBulkActions, createToast } from '@/utils'
|
import { setupListActions, createToast } from '@/utils'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { onMounted, ref, watch } from 'vue'
|
import { onMounted, ref, watch } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
@ -243,6 +243,7 @@ function deleteValues(selections, unselectAll) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const customBulkActions = ref([])
|
const customBulkActions = ref([])
|
||||||
|
const customListActions = ref([])
|
||||||
|
|
||||||
function bulkActions(selections, unselectAll) {
|
function bulkActions(selections, unselectAll) {
|
||||||
let actions = [
|
let actions = [
|
||||||
@ -275,7 +276,18 @@ function bulkActions(selections, unselectAll) {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!list.value?.data) return
|
if (!list.value?.data) return
|
||||||
setupBulkActions(list.value.data)
|
setupListActions(list.value.data, {
|
||||||
|
list: list.value,
|
||||||
|
call,
|
||||||
|
createToast,
|
||||||
|
$dialog,
|
||||||
|
router,
|
||||||
|
})
|
||||||
customBulkActions.value = list.value?.data?.bulkActions || []
|
customBulkActions.value = list.value?.data?.bulkActions || []
|
||||||
|
customListActions.value = list.value?.data?.listActions || []
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
customListActions,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -88,7 +88,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import EditValueModal from '@/components/Modals/EditValueModal.vue'
|
import EditValueModal from '@/components/Modals/EditValueModal.vue'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { createToast } from '@/utils'
|
import { setupListActions, createToast } from '@/utils'
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
ListView,
|
ListView,
|
||||||
@ -102,7 +102,8 @@ import {
|
|||||||
Dropdown,
|
Dropdown,
|
||||||
call,
|
call,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch, onMounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
rows: {
|
rows: {
|
||||||
@ -135,6 +136,8 @@ const emit = defineEmits([
|
|||||||
const pageLengthCount = defineModel()
|
const pageLengthCount = defineModel()
|
||||||
const list = defineModel('list')
|
const list = defineModel('list')
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const { $dialog } = globalStore()
|
const { $dialog } = globalStore()
|
||||||
|
|
||||||
watch(pageLengthCount, (val, old_value) => {
|
watch(pageLengthCount, (val, old_value) => {
|
||||||
@ -184,6 +187,8 @@ function deleteValues(selections, unselectAll) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customListActions = ref([])
|
||||||
|
|
||||||
function bulkActions(selections, unselectAll) {
|
function bulkActions(selections, unselectAll) {
|
||||||
let actions = [
|
let actions = [
|
||||||
{
|
{
|
||||||
@ -197,4 +202,21 @@ function bulkActions(selections, unselectAll) {
|
|||||||
]
|
]
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!list.value?.data) return
|
||||||
|
setupListActions(list.value.data, {
|
||||||
|
list: list.value,
|
||||||
|
call,
|
||||||
|
createToast,
|
||||||
|
$dialog,
|
||||||
|
router,
|
||||||
|
})
|
||||||
|
// customBulkActions.value = list.value?.data?.bulkActions || []
|
||||||
|
customListActions.value = list.value?.data?.listActions || []
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
customListActions,
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -106,7 +106,7 @@ import CalendarIcon from '@/components/Icons/CalendarIcon.vue'
|
|||||||
import EditValueModal from '@/components/Modals/EditValueModal.vue'
|
import EditValueModal from '@/components/Modals/EditValueModal.vue'
|
||||||
import { dateFormat } from '@/utils'
|
import { dateFormat } from '@/utils'
|
||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { createToast } from '@/utils'
|
import { setupListActions, createToast } from '@/utils'
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
ListView,
|
ListView,
|
||||||
@ -120,7 +120,8 @@ import {
|
|||||||
call,
|
call,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch, onMounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
rows: {
|
rows: {
|
||||||
@ -154,6 +155,8 @@ const emit = defineEmits([
|
|||||||
const pageLengthCount = defineModel()
|
const pageLengthCount = defineModel()
|
||||||
const list = defineModel('list')
|
const list = defineModel('list')
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const { $dialog } = globalStore()
|
const { $dialog } = globalStore()
|
||||||
|
|
||||||
watch(pageLengthCount, (val, old_value) => {
|
watch(pageLengthCount, (val, old_value) => {
|
||||||
@ -203,6 +206,8 @@ function deleteValues(selections, unselectAll) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customListActions = ref([])
|
||||||
|
|
||||||
function bulkActions(selections, unselectAll) {
|
function bulkActions(selections, unselectAll) {
|
||||||
let actions = [
|
let actions = [
|
||||||
{
|
{
|
||||||
@ -216,4 +221,21 @@ function bulkActions(selections, unselectAll) {
|
|||||||
]
|
]
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!list.value?.data) return
|
||||||
|
setupListActions(list.value.data, {
|
||||||
|
list: list.value,
|
||||||
|
call,
|
||||||
|
createToast,
|
||||||
|
$dialog,
|
||||||
|
router,
|
||||||
|
})
|
||||||
|
// customBulkActions.value = list.value?.data?.bulkActions || []
|
||||||
|
customListActions.value = list.value?.data?.listActions || []
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
customListActions,
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -3,6 +3,12 @@
|
|||||||
<template #left-header>
|
<template #left-header>
|
||||||
<Breadcrumbs :items="breadcrumbs" />
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
</template>
|
</template>
|
||||||
|
<template #right-header>
|
||||||
|
<CustomActions
|
||||||
|
v-if="callLogsListView?.customListActions"
|
||||||
|
:actions="callLogsListView.customListActions"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</LayoutHeader>
|
</LayoutHeader>
|
||||||
<ViewControls
|
<ViewControls
|
||||||
ref="viewControls"
|
ref="viewControls"
|
||||||
@ -13,6 +19,7 @@
|
|||||||
doctype="CRM Call Log"
|
doctype="CRM Call Log"
|
||||||
/>
|
/>
|
||||||
<CallLogsListView
|
<CallLogsListView
|
||||||
|
ref="callLogsListView"
|
||||||
v-if="callLogs.data && rows.length"
|
v-if="callLogs.data && rows.length"
|
||||||
v-model="callLogs.data.page_length_count"
|
v-model="callLogs.data.page_length_count"
|
||||||
v-model:list="callLogs"
|
v-model:list="callLogs"
|
||||||
@ -43,6 +50,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import CustomActions from '@/components/CustomActions.vue'
|
||||||
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
import PhoneIcon from '@/components/Icons/PhoneIcon.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'
|
||||||
@ -63,6 +71,8 @@ const { getContact, getLeadContact } = contactsStore()
|
|||||||
|
|
||||||
const breadcrumbs = [{ label: 'Call Logs', route: { name: 'Call Logs' } }]
|
const breadcrumbs = [{ label: 'Call Logs', route: { name: 'Call Logs' } }]
|
||||||
|
|
||||||
|
const callLogsListView = ref(null)
|
||||||
|
|
||||||
// callLogs data is loaded in the ViewControls component
|
// callLogs data is loaded in the ViewControls component
|
||||||
const callLogs = ref({})
|
const callLogs = ref({})
|
||||||
const loadMore = ref(1)
|
const loadMore = ref(1)
|
||||||
|
|||||||
@ -4,6 +4,10 @@
|
|||||||
<Breadcrumbs :items="breadcrumbs" />
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
</template>
|
</template>
|
||||||
<template #right-header>
|
<template #right-header>
|
||||||
|
<CustomActions
|
||||||
|
v-if="contactsListView?.customListActions"
|
||||||
|
:actions="contactsListView.customListActions"
|
||||||
|
/>
|
||||||
<Button variant="solid" label="Create" @click="showContactModal = true">
|
<Button variant="solid" label="Create" @click="showContactModal = true">
|
||||||
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
||||||
</Button>
|
</Button>
|
||||||
@ -18,6 +22,7 @@
|
|||||||
doctype="Contact"
|
doctype="Contact"
|
||||||
/>
|
/>
|
||||||
<ContactsListView
|
<ContactsListView
|
||||||
|
ref="contactsListView"
|
||||||
v-if="contacts.data && rows.length"
|
v-if="contacts.data && rows.length"
|
||||||
v-model="contacts.data.page_length_count"
|
v-model="contacts.data.page_length_count"
|
||||||
v-model:list="contacts"
|
v-model:list="contacts"
|
||||||
@ -52,6 +57,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import CustomActions from '@/components/CustomActions.vue'
|
||||||
import ContactsIcon from '@/components/Icons/ContactsIcon.vue'
|
import ContactsIcon from '@/components/Icons/ContactsIcon.vue'
|
||||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||||
import ContactModal from '@/components/Modals/ContactModal.vue'
|
import ContactModal from '@/components/Modals/ContactModal.vue'
|
||||||
@ -87,6 +93,8 @@ const breadcrumbs = computed(() => {
|
|||||||
return items
|
return items
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const contactsListView = ref(null)
|
||||||
|
|
||||||
// contacts data is loaded in the ViewControls component
|
// contacts data is loaded in the ViewControls component
|
||||||
const contacts = ref({})
|
const contacts = ref({})
|
||||||
const loadMore = ref(1)
|
const loadMore = ref(1)
|
||||||
|
|||||||
@ -4,6 +4,10 @@
|
|||||||
<Breadcrumbs :items="breadcrumbs" />
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
</template>
|
</template>
|
||||||
<template #right-header>
|
<template #right-header>
|
||||||
|
<CustomActions
|
||||||
|
v-if="dealsListView?.customListActions"
|
||||||
|
:actions="dealsListView.customListActions"
|
||||||
|
/>
|
||||||
<Button variant="solid" label="Create" @click="showNewDialog = true">
|
<Button variant="solid" label="Create" @click="showNewDialog = true">
|
||||||
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
||||||
</Button>
|
</Button>
|
||||||
@ -18,6 +22,7 @@
|
|||||||
doctype="CRM Deal"
|
doctype="CRM Deal"
|
||||||
/>
|
/>
|
||||||
<DealsListView
|
<DealsListView
|
||||||
|
ref="dealsListView"
|
||||||
v-if="deals.data && rows.length"
|
v-if="deals.data && rows.length"
|
||||||
v-model="deals.data.page_length_count"
|
v-model="deals.data.page_length_count"
|
||||||
v-model:list="deals"
|
v-model:list="deals"
|
||||||
@ -65,6 +70,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import CustomActions from '@/components/CustomActions.vue'
|
||||||
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
import DealsIcon from '@/components/Icons/DealsIcon.vue'
|
||||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||||
import DealsListView from '@/components/ListViews/DealsListView.vue'
|
import DealsListView from '@/components/ListViews/DealsListView.vue'
|
||||||
@ -92,6 +98,8 @@ const { getDealStatus } = statusesStore()
|
|||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
const dealsListView = ref(null)
|
||||||
|
|
||||||
// deals data is loaded in the ViewControls component
|
// deals data is loaded in the ViewControls component
|
||||||
const deals = ref({})
|
const deals = ref({})
|
||||||
const loadMore = ref(1)
|
const loadMore = ref(1)
|
||||||
|
|||||||
@ -4,6 +4,10 @@
|
|||||||
<Breadcrumbs :items="breadcrumbs" />
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
</template>
|
</template>
|
||||||
<template #right-header>
|
<template #right-header>
|
||||||
|
<CustomActions
|
||||||
|
v-if="emailTemplatesListView?.customListActions"
|
||||||
|
:actions="emailTemplatesListView.customListActions"
|
||||||
|
/>
|
||||||
<Button variant="solid" label="Create" @click="showEmailTemplateModal = true">
|
<Button variant="solid" label="Create" @click="showEmailTemplateModal = true">
|
||||||
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
||||||
</Button>
|
</Button>
|
||||||
@ -18,6 +22,7 @@
|
|||||||
doctype="Email Template"
|
doctype="Email Template"
|
||||||
/>
|
/>
|
||||||
<EmailTemplatesListView
|
<EmailTemplatesListView
|
||||||
|
ref="emailTemplatesListView"
|
||||||
v-if="emailTemplates.data && rows.length"
|
v-if="emailTemplates.data && rows.length"
|
||||||
v-model="emailTemplates.data.page_length_count"
|
v-model="emailTemplates.data.page_length_count"
|
||||||
v-model:list="emailTemplates"
|
v-model:list="emailTemplates"
|
||||||
@ -54,6 +59,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import CustomActions from '@/components/CustomActions.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'
|
||||||
@ -67,6 +73,8 @@ const breadcrumbs = [
|
|||||||
{ label: 'Email Templates', route: { name: 'Email Templates' } },
|
{ label: 'Email Templates', route: { name: 'Email Templates' } },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const emailTemplatesListView = ref(null)
|
||||||
|
|
||||||
// emailTemplates data is loaded in the ViewControls component
|
// emailTemplates data is loaded in the ViewControls component
|
||||||
const emailTemplates = ref({})
|
const emailTemplates = ref({})
|
||||||
const loadMore = ref(1)
|
const loadMore = ref(1)
|
||||||
|
|||||||
@ -4,6 +4,10 @@
|
|||||||
<Breadcrumbs :items="breadcrumbs" />
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
</template>
|
</template>
|
||||||
<template #right-header>
|
<template #right-header>
|
||||||
|
<CustomActions
|
||||||
|
v-if="leadsListView?.customListActions"
|
||||||
|
:actions="leadsListView.customListActions"
|
||||||
|
/>
|
||||||
<Button variant="solid" label="Create" @click="showNewDialog = true">
|
<Button variant="solid" label="Create" @click="showNewDialog = true">
|
||||||
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
||||||
</Button>
|
</Button>
|
||||||
@ -19,6 +23,7 @@
|
|||||||
:filters="{ converted: 0 }"
|
:filters="{ converted: 0 }"
|
||||||
/>
|
/>
|
||||||
<LeadsListView
|
<LeadsListView
|
||||||
|
ref="leadsListView"
|
||||||
v-if="leads.data && rows.length"
|
v-if="leads.data && rows.length"
|
||||||
v-model="leads.data.page_length_count"
|
v-model="leads.data.page_length_count"
|
||||||
v-model:list="leads"
|
v-model:list="leads"
|
||||||
@ -66,6 +71,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import CustomActions from '@/components/CustomActions.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'
|
||||||
import LeadsListView from '@/components/ListViews/LeadsListView.vue'
|
import LeadsListView from '@/components/ListViews/LeadsListView.vue'
|
||||||
@ -87,6 +93,8 @@ const { getLeadStatus } = statusesStore()
|
|||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
const leadsListView = ref(null)
|
||||||
|
|
||||||
// leads data is loaded in the ViewControls component
|
// leads data is loaded in the ViewControls component
|
||||||
const leads = ref({})
|
const leads = ref({})
|
||||||
const loadMore = ref(1)
|
const loadMore = ref(1)
|
||||||
|
|||||||
@ -4,6 +4,10 @@
|
|||||||
<Breadcrumbs :items="breadcrumbs" />
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
</template>
|
</template>
|
||||||
<template #right-header>
|
<template #right-header>
|
||||||
|
<CustomActions
|
||||||
|
v-if="organizationsListView?.customListActions"
|
||||||
|
:actions="organizationsListView.customListActions"
|
||||||
|
/>
|
||||||
<Button
|
<Button
|
||||||
variant="solid"
|
variant="solid"
|
||||||
label="Create"
|
label="Create"
|
||||||
@ -22,6 +26,7 @@
|
|||||||
doctype="CRM Organization"
|
doctype="CRM Organization"
|
||||||
/>
|
/>
|
||||||
<OrganizationsListView
|
<OrganizationsListView
|
||||||
|
ref="organizationsListView"
|
||||||
v-if="organizations.data && rows.length"
|
v-if="organizations.data && rows.length"
|
||||||
v-model="organizations.data.page_length_count"
|
v-model="organizations.data.page_length_count"
|
||||||
v-model:list="organizations"
|
v-model:list="organizations"
|
||||||
@ -55,6 +60,7 @@
|
|||||||
<OrganizationModal v-model="showOrganizationModal" />
|
<OrganizationModal v-model="showOrganizationModal" />
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import CustomActions from '@/components/CustomActions.vue'
|
||||||
import OrganizationsIcon from '@/components/Icons/OrganizationsIcon.vue'
|
import OrganizationsIcon from '@/components/Icons/OrganizationsIcon.vue'
|
||||||
import LayoutHeader from '@/components/LayoutHeader.vue'
|
import LayoutHeader from '@/components/LayoutHeader.vue'
|
||||||
import OrganizationModal from '@/components/Modals/OrganizationModal.vue'
|
import OrganizationModal from '@/components/Modals/OrganizationModal.vue'
|
||||||
@ -72,6 +78,7 @@ import { useRoute } from 'vue-router'
|
|||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
const organizationsListView = ref(null)
|
||||||
const showOrganizationModal = ref(false)
|
const showOrganizationModal = ref(false)
|
||||||
|
|
||||||
const currentOrganization = computed(() => {
|
const currentOrganization = computed(() => {
|
||||||
|
|||||||
@ -4,6 +4,10 @@
|
|||||||
<Breadcrumbs :items="breadcrumbs" />
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
</template>
|
</template>
|
||||||
<template #right-header>
|
<template #right-header>
|
||||||
|
<CustomActions
|
||||||
|
v-if="tasksListView?.customListActions"
|
||||||
|
:actions="tasksListView.customListActions"
|
||||||
|
/>
|
||||||
<Button variant="solid" label="Create" @click="createTask">
|
<Button variant="solid" label="Create" @click="createTask">
|
||||||
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
||||||
</Button>
|
</Button>
|
||||||
@ -18,6 +22,7 @@
|
|||||||
doctype="CRM Task"
|
doctype="CRM Task"
|
||||||
/>
|
/>
|
||||||
<TasksListView
|
<TasksListView
|
||||||
|
ref="tasksListView"
|
||||||
v-if="tasks.data && rows.length"
|
v-if="tasks.data && rows.length"
|
||||||
v-model="tasks.data.page_length_count"
|
v-model="tasks.data.page_length_count"
|
||||||
v-model:list="tasks"
|
v-model:list="tasks"
|
||||||
@ -47,6 +52,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import CustomActions from '@/components/CustomActions.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'
|
||||||
@ -61,6 +67,8 @@ const breadcrumbs = [{ label: 'Tasks', route: { name: 'Tasks' } }]
|
|||||||
|
|
||||||
const { getUser } = usersStore()
|
const { getUser } = usersStore()
|
||||||
|
|
||||||
|
const tasksListView = ref(null)
|
||||||
|
|
||||||
// tasks data is loaded in the ViewControls component
|
// tasks data is loaded in the ViewControls component
|
||||||
const tasks = ref({})
|
const tasks = ref({})
|
||||||
const loadMore = ref(1)
|
const loadMore = ref(1)
|
||||||
|
|||||||
@ -131,11 +131,12 @@ export function setupCustomActions(data, obj) {
|
|||||||
data._customActions = formScript?.actions || []
|
data._customActions = formScript?.actions || []
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupBulkActions(data, obj = {}) {
|
export function setupListActions(data, obj = {}) {
|
||||||
if (!data.form_script) return []
|
if (!data.list_script) return []
|
||||||
let script = new Function(data.form_script + '\nreturn setupForm')()
|
let script = new Function(data.list_script + '\nreturn setupList')()
|
||||||
let formScript = script(obj)
|
let listScript = script(obj)
|
||||||
data.bulkActions = formScript?.bulk_actions || []
|
data.listActions = listScript?.actions || []
|
||||||
|
data.bulkActions = listScript?.bulk_actions || []
|
||||||
}
|
}
|
||||||
|
|
||||||
export function errorMessage(title, message) {
|
export function errorMessage(title, message) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user