1
0
forked from test/crm

refactor: note dialog and code

This commit is contained in:
Shariq Ansari 2023-09-28 19:04:46 +05:30
parent 02348542c6
commit c20d296b35
3 changed files with 96 additions and 100 deletions

View File

@ -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({})

View File

@ -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
}
}) })
} }
) )

View File

@ -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',