refactor: note dialog and code
This commit is contained in:
parent
02348542c6
commit
c20d296b35
@ -523,7 +523,12 @@
|
||||
v-model="lead"
|
||||
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
|
||||
v-model="showTaskModal"
|
||||
v-model:reloadTasks="tasks"
|
||||
@ -798,10 +803,7 @@ function timelineIcon(activity_type, is_lead) {
|
||||
|
||||
// Notes
|
||||
const showNoteModal = ref(false)
|
||||
const note = ref({
|
||||
title: '',
|
||||
content: '',
|
||||
})
|
||||
const note = ref({})
|
||||
|
||||
function showNote(n) {
|
||||
note.value = n || {
|
||||
@ -819,31 +821,6 @@ async function deleteNote(name) {
|
||||
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
|
||||
const showTaskModal = ref(false)
|
||||
const task = ref({})
|
||||
|
||||
@ -1,70 +1,111 @@
|
||||
<template>
|
||||
<Dialog v-model="show" :options="{ size: '4xl' }" @close="updateNote">
|
||||
<template #body-title><div></div></template>
|
||||
<Dialog
|
||||
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>
|
||||
<div
|
||||
class="flex flex-col gap-2 px-20 mt-5 mb-10 min-h-[400px] max-h-[500px] overflow-auto"
|
||||
>
|
||||
<TextInput
|
||||
ref="title"
|
||||
type="text"
|
||||
class="!text-[30px] !h-10 !font-semibold bg-white border-none hover:bg-white focus:!shadow-none focus-visible:!ring-0"
|
||||
v-model="updatedNote.title"
|
||||
placeholder="Untitled note"
|
||||
/>
|
||||
<TextEditor
|
||||
ref="content"
|
||||
editor-class="!prose-sm !leading-5 max-w-none p-2 overflow-auto focus:outline-none"
|
||||
:bubbleMenu="true"
|
||||
:content="updatedNote.content"
|
||||
@change="(val) => (updatedNote.content = val)"
|
||||
placeholder="Type something and press enter"
|
||||
/>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div>
|
||||
<div class="mb-1.5 text-sm text-gray-600">Title</div>
|
||||
<TextInput
|
||||
ref="title"
|
||||
variant="outline"
|
||||
v-model="_note.title"
|
||||
placeholder="Add title"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-1.5 text-sm text-gray-600">Content</div>
|
||||
<TextEditor
|
||||
variant="outline"
|
||||
ref="content"
|
||||
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"
|
||||
:bubbleMenu="true"
|
||||
:content="_note.content"
|
||||
@change="(val) => (_note.content = val)"
|
||||
placeholder="Type a content"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { TextInput, TextEditor, Dialog } from 'frappe-ui'
|
||||
import { TextInput, TextEditor, Dialog, call } from 'frappe-ui'
|
||||
import { ref, defineModel, nextTick, watch } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
note: {
|
||||
type: Object,
|
||||
default: {
|
||||
title: '',
|
||||
content: '',
|
||||
},
|
||||
default: {},
|
||||
},
|
||||
lead: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const show = defineModel()
|
||||
const emit = defineEmits(['updateNote'])
|
||||
const notes = defineModel('reloadNotes')
|
||||
|
||||
const title = ref(null)
|
||||
const editMode = ref(false)
|
||||
let _note = ref({})
|
||||
|
||||
let updatedNote = ref({
|
||||
title: '',
|
||||
content: '',
|
||||
})
|
||||
|
||||
function updateNote() {
|
||||
async function updateNote(close) {
|
||||
if (
|
||||
props.note.title !== updatedNote.value.title ||
|
||||
props.note.content !== updatedNote.value.content
|
||||
) {
|
||||
emit('updateNote', updatedNote.value)
|
||||
props.note.title === _note.value.title &&
|
||||
props.note.content === _note.value.content
|
||||
)
|
||||
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(
|
||||
() => show.value,
|
||||
(value) => {
|
||||
if (!value) return
|
||||
editMode.value = false
|
||||
nextTick(() => {
|
||||
title.value.el.focus()
|
||||
updatedNote.value = { ...props.note }
|
||||
_note.value = { ...props.note }
|
||||
if (_note.value.title) {
|
||||
editMode.value = true
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
@ -9,14 +9,17 @@
|
||||
</Button>
|
||||
</template>
|
||||
</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
|
||||
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)"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-lg font-medium truncate">
|
||||
<div class="truncate text-lg font-medium">
|
||||
{{ note.title }}
|
||||
</div>
|
||||
<Dropdown
|
||||
@ -43,7 +46,7 @@
|
||||
editor-class="!prose-sm max-w-none !text-sm text-gray-600 focus:outline-none"
|
||||
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">
|
||||
<UserAvatar :user="note.owner" size="xs" />
|
||||
<div class="text-sm text-gray-800">
|
||||
@ -60,17 +63,17 @@
|
||||
</div>
|
||||
<div
|
||||
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">
|
||||
<NoteIcon class="w-10 h-10 text-gray-500" />
|
||||
<NoteIcon class="h-10 w-10 text-gray-500" />
|
||||
<span>No notes</span>
|
||||
</div>
|
||||
</div>
|
||||
<NoteModal
|
||||
v-model="showNoteModal"
|
||||
v-model:reloadNotes="notes"
|
||||
:note="currentNote"
|
||||
@updateNote="updateNote"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@ -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',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user