refactor: note dialog and code
This commit is contained in:
parent
02348542c6
commit
c20d296b35
@ -523,7 +523,12 @@
|
|||||||
v-model="lead"
|
v-model="lead"
|
||||||
v-model:reload="reload_email"
|
v-model:reload="reload_email"
|
||||||
/>
|
/>
|
||||||
<NoteModal v-model="showNoteModal" :note="note" @updateNote="updateNote" />
|
<NoteModal
|
||||||
|
v-model="showNoteModal"
|
||||||
|
v-model:reloadNotes="notes"
|
||||||
|
:note="note"
|
||||||
|
:lead="lead.data?.name"
|
||||||
|
/>
|
||||||
<TaskModal
|
<TaskModal
|
||||||
v-model="showTaskModal"
|
v-model="showTaskModal"
|
||||||
v-model:reloadTasks="tasks"
|
v-model:reloadTasks="tasks"
|
||||||
@ -798,10 +803,7 @@ function timelineIcon(activity_type, is_lead) {
|
|||||||
|
|
||||||
// Notes
|
// Notes
|
||||||
const showNoteModal = ref(false)
|
const showNoteModal = ref(false)
|
||||||
const note = ref({
|
const note = ref({})
|
||||||
title: '',
|
|
||||||
content: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
function showNote(n) {
|
function showNote(n) {
|
||||||
note.value = n || {
|
note.value = n || {
|
||||||
@ -819,31 +821,6 @@ async function deleteNote(name) {
|
|||||||
notes.reload()
|
notes.reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|
||||||
lead: lead.value.data.name,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if (d.name) {
|
|
||||||
notes.reload()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tasks
|
// Tasks
|
||||||
const showTaskModal = ref(false)
|
const showTaskModal = ref(false)
|
||||||
const task = ref({})
|
const task = ref({})
|
||||||
|
|||||||
@ -1,70 +1,111 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog v-model="show" :options="{ size: '4xl' }" @close="updateNote">
|
<Dialog
|
||||||
<template #body-title><div></div></template>
|
v-model="show"
|
||||||
|
:options="{
|
||||||
|
title: editMode ? 'Edit Note' : 'Create Note',
|
||||||
|
size: 'xl',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
label: editMode ? 'Update' : 'Create',
|
||||||
|
variant: 'solid',
|
||||||
|
onClick: ({ close }) => updateNote(close),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}"
|
||||||
|
>
|
||||||
<template #body-content>
|
<template #body-content>
|
||||||
<div
|
<div class="flex flex-col gap-4">
|
||||||
class="flex flex-col gap-2 px-20 mt-5 mb-10 min-h-[400px] max-h-[500px] overflow-auto"
|
<div>
|
||||||
>
|
<div class="mb-1.5 text-sm text-gray-600">Title</div>
|
||||||
<TextInput
|
<TextInput
|
||||||
ref="title"
|
ref="title"
|
||||||
type="text"
|
variant="outline"
|
||||||
class="!text-[30px] !h-10 !font-semibold bg-white border-none hover:bg-white focus:!shadow-none focus-visible:!ring-0"
|
v-model="_note.title"
|
||||||
v-model="updatedNote.title"
|
placeholder="Add title"
|
||||||
placeholder="Untitled note"
|
/>
|
||||||
/>
|
</div>
|
||||||
<TextEditor
|
<div>
|
||||||
ref="content"
|
<div class="mb-1.5 text-sm text-gray-600">Content</div>
|
||||||
editor-class="!prose-sm !leading-5 max-w-none p-2 overflow-auto focus:outline-none"
|
<TextEditor
|
||||||
:bubbleMenu="true"
|
variant="outline"
|
||||||
:content="updatedNote.content"
|
ref="content"
|
||||||
@change="(val) => (updatedNote.content = val)"
|
editor-class="!prose-sm overflow-auto min-h-[180px] max-h-80 py-1.5 px-2 rounded border border-gray-300 bg-white hover:border-gray-400 hover:shadow-sm focus:bg-white focus:border-gray-500 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-gray-400 text-gray-800 transition-colors"
|
||||||
placeholder="Type something and press enter"
|
:bubbleMenu="true"
|
||||||
/>
|
:content="_note.content"
|
||||||
|
@change="(val) => (_note.content = val)"
|
||||||
|
placeholder="Type a content"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { TextInput, TextEditor, Dialog } from 'frappe-ui'
|
import { TextInput, TextEditor, Dialog, call } from 'frappe-ui'
|
||||||
import { ref, defineModel, nextTick, watch } from 'vue'
|
import { ref, defineModel, nextTick, watch } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
note: {
|
note: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: {
|
default: {},
|
||||||
title: '',
|
},
|
||||||
content: '',
|
lead: {
|
||||||
},
|
type: String,
|
||||||
|
default: '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const show = defineModel()
|
const show = defineModel()
|
||||||
const emit = defineEmits(['updateNote'])
|
const notes = defineModel('reloadNotes')
|
||||||
|
|
||||||
const title = ref(null)
|
const title = ref(null)
|
||||||
|
const editMode = ref(false)
|
||||||
|
let _note = ref({})
|
||||||
|
|
||||||
let updatedNote = ref({
|
async function updateNote(close) {
|
||||||
title: '',
|
|
||||||
content: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
function updateNote() {
|
|
||||||
if (
|
if (
|
||||||
props.note.title !== updatedNote.value.title ||
|
props.note.title === _note.value.title &&
|
||||||
props.note.content !== updatedNote.value.content
|
props.note.content === _note.value.content
|
||||||
) {
|
)
|
||||||
emit('updateNote', updatedNote.value)
|
return
|
||||||
|
|
||||||
|
if (_note.value.name) {
|
||||||
|
let d = await call('frappe.client.set_value', {
|
||||||
|
doctype: 'CRM Note',
|
||||||
|
name: _note.value.name,
|
||||||
|
fieldname: _note.value,
|
||||||
|
})
|
||||||
|
if (d.name) {
|
||||||
|
notes.value.reload()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let d = await call('frappe.client.insert', {
|
||||||
|
doc: {
|
||||||
|
doctype: 'CRM Note',
|
||||||
|
title: _note.value.title,
|
||||||
|
content: _note.value.content,
|
||||||
|
lead: props.lead || '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (d.name) {
|
||||||
|
notes.value.reload()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
close()
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => show.value,
|
() => show.value,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (!value) return
|
if (!value) return
|
||||||
|
editMode.value = false
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
title.value.el.focus()
|
title.value.el.focus()
|
||||||
updatedNote.value = { ...props.note }
|
_note.value = { ...props.note }
|
||||||
|
if (_note.value.title) {
|
||||||
|
editMode.value = true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@ -9,14 +9,17 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</LayoutHeader>
|
</LayoutHeader>
|
||||||
<div v-if="notes.data?.length" class="grid grid-cols-4 gap-4 p-5 overflow-y-auto">
|
<div
|
||||||
|
v-if="notes.data?.length"
|
||||||
|
class="grid grid-cols-4 gap-4 overflow-y-auto p-5"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="note in notes.data"
|
v-for="note in notes.data"
|
||||||
class="group flex flex-col justify-between gap-2 px-5 py-4 border rounded-lg h-56 shadow-sm hover:bg-gray-50 cursor-pointer"
|
class="group flex h-56 cursor-pointer flex-col justify-between gap-2 rounded-lg border px-5 py-4 shadow-sm hover:bg-gray-50"
|
||||||
@click="editNote(note)"
|
@click="editNote(note)"
|
||||||
>
|
>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class="text-lg font-medium truncate">
|
<div class="truncate text-lg font-medium">
|
||||||
{{ note.title }}
|
{{ note.title }}
|
||||||
</div>
|
</div>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
@ -43,7 +46,7 @@
|
|||||||
editor-class="!prose-sm max-w-none !text-sm text-gray-600 focus:outline-none"
|
editor-class="!prose-sm max-w-none !text-sm text-gray-600 focus:outline-none"
|
||||||
class="flex-1 overflow-hidden"
|
class="flex-1 overflow-hidden"
|
||||||
/>
|
/>
|
||||||
<div class="flex items-center justify-between gap-2 mt-2">
|
<div class="mt-2 flex items-center justify-between gap-2">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<UserAvatar :user="note.owner" size="xs" />
|
<UserAvatar :user="note.owner" size="xs" />
|
||||||
<div class="text-sm text-gray-800">
|
<div class="text-sm text-gray-800">
|
||||||
@ -60,17 +63,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="flex-1 p-5 flex items-center justify-center font-medium text-xl text-gray-500"
|
class="flex flex-1 items-center justify-center p-5 text-xl font-medium text-gray-500"
|
||||||
>
|
>
|
||||||
<div class="flex flex-col items-center gap-2">
|
<div class="flex flex-col items-center gap-2">
|
||||||
<NoteIcon class="w-10 h-10 text-gray-500" />
|
<NoteIcon class="h-10 w-10 text-gray-500" />
|
||||||
<span>No notes</span>
|
<span>No notes</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<NoteModal
|
<NoteModal
|
||||||
v-model="showNoteModal"
|
v-model="showNoteModal"
|
||||||
|
v-model:reloadNotes="notes"
|
||||||
:note="currentNote"
|
:note="currentNote"
|
||||||
@updateNote="updateNote"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -86,10 +89,9 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
createListResource,
|
createListResource,
|
||||||
TextEditor,
|
TextEditor,
|
||||||
TextInput,
|
|
||||||
call,
|
call,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
@ -129,30 +131,6 @@ function editNote(note) {
|
|||||||
showNoteModal.value = true
|
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) {
|
async function deleteNote(name) {
|
||||||
await call('frappe.client.delete', {
|
await call('frappe.client.delete', {
|
||||||
doctype: 'CRM Note',
|
doctype: 'CRM Note',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user