@@ -60,17 +63,17 @@
@@ -86,10 +89,9 @@ import {
Button,
createListResource,
TextEditor,
- TextInput,
call,
Dropdown,
-Tooltip,
+ Tooltip,
} from 'frappe-ui'
import { ref } from 'vue'
import { usersStore } from '@/stores/users'
@@ -129,30 +131,6 @@ function editNote(note) {
showNoteModal.value = true
}
-async function updateNote(note) {
- if (note.name) {
- let d = await call('frappe.client.set_value', {
- doctype: 'CRM Note',
- name: note.name,
- fieldname: note,
- })
- if (d.name) {
- notes.reload()
- }
- } else {
- let d = await call('frappe.client.insert', {
- doc: {
- doctype: 'CRM Note',
- title: note.title,
- content: note.content,
- },
- })
- if (d.name) {
- notes.reload()
- }
- }
-}
-
async function deleteNote(name) {
await call('frappe.client.delete', {
doctype: 'CRM Note',
diff --git a/frontend/src/utils/dialogs.js b/frontend/src/utils/dialogs.js
new file mode 100644
index 00000000..9efdde3b
--- /dev/null
+++ b/frontend/src/utils/dialogs.js
@@ -0,0 +1,31 @@
+import { Dialog, ErrorMessage } from 'frappe-ui'
+import { h, reactive, ref } from 'vue'
+
+let dialogs = ref([])
+
+export let Dialogs = {
+ name: 'Dialogs',
+ render() {
+ return dialogs.value.map((dialog) => {
+ return h(
+ Dialog,
+ {
+ options: dialog,
+ modelValue: dialog.show,
+ 'onUpdate:modelValue': (val) => (dialog.show = val),
+ },
+ () => [
+ h('p', { class: 'text-p-base text-gray-700' }, dialog.message),
+ h(ErrorMessage, { class: 'mt-2', message: dialog.error }),
+ ]
+ )
+ })
+ },
+}
+
+export function createDialog(options) {
+ let dialog = reactive(options)
+ dialog.key = `dialog-${Math.random().toString(36).slice(2, 9)}`
+ dialogs.value.push(dialog)
+ dialog.show = true
+}
diff --git a/frontend/src/utils.js b/frontend/src/utils/index.js
similarity index 72%
rename from frontend/src/utils.js
rename to frontend/src/utils/index.js
index 37e5eced..5e32abac 100644
--- a/frontend/src/utils.js
+++ b/frontend/src/utils/index.js
@@ -1,7 +1,10 @@
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
+import TaskStatusIcon from '@/components/Icons/TaskStatusIcon.vue'
+import TaskPriorityIcon from '@/components/Icons/TaskPriorityIcon.vue'
+import { usersStore } from '@/stores/users'
import { useDateFormat, useTimeAgo } from '@vueuse/core'
import { toast } from 'frappe-ui'
-import { h } from 'vue'
+import { h, computed } from 'vue'
export function createToast(options) {
toast({
@@ -91,6 +94,28 @@ export function statusDropdownOptions(data, doctype, action) {
return options
}
+export function taskStatusOptions(action, data) {
+ return ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled'].map(
+ (status) => {
+ return {
+ icon: () => h(TaskStatusIcon, { status }),
+ label: status,
+ onClick: () => action && action(status, data),
+ }
+ }
+ )
+}
+
+export function taskPriorityOptions(action, data) {
+ return ['Low', 'Medium', 'High'].map((priority) => {
+ return {
+ label: priority,
+ icon: () => h(TaskPriorityIcon, { priority }),
+ onClick: () => action && action(priority, data),
+ }
+ })
+}
+
export function openWebsite(url) {
window.open(url, '_blank')
}
@@ -128,3 +153,19 @@ export function formatNumberIntoCurrency(value) {
export function startCase(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
+
+const { users } = usersStore()
+
+export const activeAgents = computed(() => {
+ const nonAgents = ['Administrator', 'Guest']
+ return users.data
+ .filter((user) => !nonAgents.includes(user.name))
+ .sort((a, b) => a.full_name - b.full_name)
+ .map((user) => {
+ return {
+ label: user.full_name,
+ value: user.email,
+ ...user,
+ }
+ })
+})