fix: update scemantic classes fro dark mode manually

This commit is contained in:
Shariq Ansari 2024-11-28 20:59:41 +05:30
parent e9afb11407
commit 7f62371837
61 changed files with 449 additions and 427 deletions

View File

@ -5,6 +5,7 @@ from frappe import _
from bs4 import BeautifulSoup
from crm.fcrm.doctype.crm_notification.crm_notification import notify_user
def on_update(self, method):
notify_mentions(self)
@ -24,25 +25,31 @@ def notify_mentions(doc):
doctype = doc.reference_doctype
if doctype.startswith("CRM "):
doctype = doctype[4:].lower()
name = reference_doc.lead_name or name if doctype == "lead" else reference_doc.organization or reference_doc.lead_name or name
name = (
reference_doc.lead_name
if doctype == "lead"
else reference_doc.organization or reference_doc.lead_name
)
notification_text = f"""
<div class="mb-2 leading-5 text-gray-600">
<span class="font-medium text-gray-900">{ owner }</span>
<div class="mb-2 leading-5 text-ink-gray-5">
<span class="font-medium text-ink-gray-9">{ owner }</span>
<span>{ _('mentioned you in {0}').format(doctype) }</span>
<span class="font-medium text-gray-900">{ name }</span>
<span class="font-medium text-ink-gray-9">{ name }</span>
</div>
"""
notify_user({
"owner": doc.owner,
"assigned_to": mention.email,
"notification_type": "Mention",
"message": doc.content,
"notification_text": notification_text,
"reference_doctype": "Comment",
"reference_docname": doc.name,
"redirect_to_doctype": doc.reference_doctype,
"redirect_to_docname": doc.reference_name,
})
notify_user(
{
"owner": doc.owner,
"assigned_to": mention.email,
"notification_type": "Mention",
"message": doc.content,
"notification_text": notification_text,
"reference_doctype": "Comment",
"reference_docname": doc.name,
"redirect_to_doctype": doc.reference_doctype,
"redirect_to_docname": doc.reference_name,
}
)
def extract_mentions(html):
@ -56,39 +63,42 @@ def extract_mentions(html):
)
return mentions
@frappe.whitelist()
def add_attachments(name: str, attachments: Iterable[str | dict]) -> None:
"""Add attachments to the given Comment
"""Add attachments to the given Comment
:param name: Comment name
:param attachments: File names or dicts with keys "fname" and "fcontent"
"""
# loop through attachments
for a in attachments:
if isinstance(a, str):
attach = frappe.db.get_value("File", {"name": a}, ["file_url", "is_private"], as_dict=1)
file_args = {
"file_url": attach.file_url,
"is_private": attach.is_private,
}
elif isinstance(a, dict) and "fcontent" in a and "fname" in a:
# dict returned by frappe.attach_print()
file_args = {
"file_name": a["fname"],
"content": a["fcontent"],
"is_private": 1,
}
else:
continue
:param name: Comment name
:param attachments: File names or dicts with keys "fname" and "fcontent"
"""
# loop through attachments
for a in attachments:
if isinstance(a, str):
attach = frappe.db.get_value(
"File", {"name": a}, ["file_url", "is_private"], as_dict=1
)
file_args = {
"file_url": attach.file_url,
"is_private": attach.is_private,
}
elif isinstance(a, dict) and "fcontent" in a and "fname" in a:
# dict returned by frappe.attach_print()
file_args = {
"file_name": a["fname"],
"content": a["fcontent"],
"is_private": 1,
}
else:
continue
file_args.update(
{
"attached_to_doctype": "Comment",
"attached_to_name": name,
"folder": "Home/Attachments",
}
)
file_args.update(
{
"attached_to_doctype": "Comment",
"attached_to_name": name,
"folder": "Home/Attachments",
}
)
_file = frappe.new_doc("File")
_file.update(file_args)
_file.save(ignore_permissions=True)
_file = frappe.new_doc("File")
_file.update(file_args)
_file.save(ignore_permissions=True)

View File

@ -2,102 +2,131 @@ import frappe
from frappe import _
from crm.fcrm.doctype.crm_notification.crm_notification import notify_user
def after_insert(doc, method):
if doc.reference_type in ["CRM Lead", "CRM Deal"] and doc.reference_name and doc.allocated_to:
fieldname = "lead_owner" if doc.reference_type == "CRM Lead" else "deal_owner"
lead_owner = frappe.db.get_value(doc.reference_type, doc.reference_name, fieldname)
if not lead_owner:
frappe.db.set_value(doc.reference_type, doc.reference_name, fieldname, doc.allocated_to)
if doc.reference_type in ["CRM Lead", "CRM Deal", "CRM Task"] and doc.reference_name and doc.allocated_to:
notify_assigned_user(doc)
def after_insert(doc, method):
if (
doc.reference_type in ["CRM Lead", "CRM Deal"]
and doc.reference_name
and doc.allocated_to
):
fieldname = "lead_owner" if doc.reference_type == "CRM Lead" else "deal_owner"
lead_owner = frappe.db.get_value(
doc.reference_type, doc.reference_name, fieldname
)
if not lead_owner:
frappe.db.set_value(
doc.reference_type, doc.reference_name, fieldname, doc.allocated_to
)
if (
doc.reference_type in ["CRM Lead", "CRM Deal", "CRM Task"]
and doc.reference_name
and doc.allocated_to
):
notify_assigned_user(doc)
def on_update(doc, method):
if doc.has_value_changed("status") and doc.status == "Cancelled" and doc.reference_type in ["CRM Lead", "CRM Deal", "CRM Task"] and doc.reference_name and doc.allocated_to:
notify_assigned_user(doc, is_cancelled=True)
if (
doc.has_value_changed("status")
and doc.status == "Cancelled"
and doc.reference_type in ["CRM Lead", "CRM Deal", "CRM Task"]
and doc.reference_name
and doc.allocated_to
):
notify_assigned_user(doc, is_cancelled=True)
def notify_assigned_user(doc, is_cancelled=False):
_doc = frappe.get_doc(doc.reference_type, doc.reference_name)
owner = frappe.get_cached_value("User", frappe.session.user, "full_name")
notification_text = get_notification_text(owner, doc, _doc, is_cancelled)
_doc = frappe.get_doc(doc.reference_type, doc.reference_name)
owner = frappe.get_cached_value("User", frappe.session.user, "full_name")
notification_text = get_notification_text(owner, doc, _doc, is_cancelled)
message = _("Your assignment on {0} {1} has been removed by {2}").format(
doc.reference_type,
doc.reference_name,
owner
) if is_cancelled else _("{0} assigned a {1} {2} to you").format(
owner,
doc.reference_type,
doc.reference_name
)
message = (
_("Your assignment on {0} {1} has been removed by {2}").format(
doc.reference_type, doc.reference_name, owner
)
if is_cancelled
else _("{0} assigned a {1} {2} to you").format(
owner, doc.reference_type, doc.reference_name
)
)
redirect_to_doctype, redirect_to_name = get_redirect_to_doc(doc)
redirect_to_doctype, redirect_to_name = get_redirect_to_doc(doc)
notify_user(
{
"owner": frappe.session.user,
"assigned_to": doc.allocated_to,
"notification_type": "Assignment",
"message": message,
"notification_text": notification_text,
"reference_doctype": doc.reference_type,
"reference_docname": doc.reference_name,
"redirect_to_doctype": redirect_to_doctype,
"redirect_to_docname": redirect_to_name,
}
)
notify_user({
"owner": frappe.session.user,
"assigned_to": doc.allocated_to,
"notification_type": "Assignment",
"message": message,
"notification_text": notification_text,
"reference_doctype": doc.reference_type,
"reference_docname": doc.reference_name,
"redirect_to_doctype": redirect_to_doctype,
"redirect_to_docname": redirect_to_name,
})
def get_notification_text(owner, doc, reference_doc, is_cancelled=False):
name = doc.reference_name
doctype = doc.reference_type
name = doc.reference_name
doctype = doc.reference_type
if doctype.startswith("CRM "):
doctype = doctype[4:].lower()
if doctype.startswith("CRM "):
doctype = doctype[4:].lower()
if doctype in ["lead", "deal"]:
name = reference_doc.lead_name or name if doctype == "lead" else reference_doc.organization or reference_doc.lead_name or name
if doctype in ["lead", "deal"]:
name = (
reference_doc.lead_name or name
if doctype == "lead"
else reference_doc.organization or reference_doc.lead_name or name
)
if is_cancelled:
return f"""
<div class="mb-2 leading-5 text-gray-600">
<span>{ _('Your assignment on {0} {1} has been removed by {2}').format(
doctype,
f'<span class="font-medium text-gray-900">{ name }</span>',
f'<span class="font-medium text-gray-900">{ owner }</span>'
) }</span>
</div>
"""
if is_cancelled:
return f"""
<div class="mb-2 leading-5 text-ink-gray-5">
<span>{ _('Your assignment on {0} {1} has been removed by {2}').format(
doctype,
f'<span class="font-medium text-ink-gray-9">{ name }</span>',
f'<span class="font-medium text-ink-gray-9">{ owner }</span>'
) }</span>
</div>
"""
return f"""
<div class="mb-2 leading-5 text-gray-600">
<span class="font-medium text-gray-900">{ owner }</span>
<span>{ _('assigned a {0} {1} to you').format(
doctype,
f'<span class="font-medium text-gray-900">{ name }</span>'
) }</span>
</div>
"""
return f"""
<div class="mb-2 leading-5 text-ink-gray-5">
<span class="font-medium text-ink-gray-9">{ owner }</span>
<span>{ _('assigned a {0} {1} to you').format(
doctype,
f'<span class="font-medium text-ink-gray-9">{ name }</span>'
) }</span>
</div>
"""
if doctype == "task":
if is_cancelled:
return f"""
<div class="mb-2 leading-5 text-ink-gray-5">
<span>{ _('Your assignment on task {0} has been removed by {1}').format(
f'<span class="font-medium text-ink-gray-9">{ reference_doc.title }</span>',
f'<span class="font-medium text-ink-gray-9">{ owner }</span>'
) }</span>
</div>
"""
return f"""
<div class="mb-2 leading-5 text-ink-gray-5">
<span class="font-medium text-ink-gray-9">{ owner }</span>
<span>{ _('assigned a new task {0} to you').format(
f'<span class="font-medium text-ink-gray-9">{ reference_doc.title }</span>'
) }</span>
</div>
"""
if doctype == "task":
if is_cancelled:
return f"""
<div class="mb-2 leading-5 text-gray-600">
<span>{ _('Your assignment on task {0} has been removed by {1}').format(
f'<span class="font-medium text-gray-900">{ reference_doc.title }</span>',
f'<span class="font-medium text-gray-900">{ owner }</span>'
) }</span>
</div>
"""
return f"""
<div class="mb-2 leading-5 text-gray-600">
<span class="font-medium text-gray-900">{ owner }</span>
<span>{ _('assigned a new task {0} to you').format(
f'<span class="font-medium text-gray-900">{ reference_doc.title }</span>'
) }</span>
</div>
"""
def get_redirect_to_doc(doc):
if doc.reference_type == "CRM Task":
reference_doc = frappe.get_doc(doc.reference_type, doc.reference_name)
return reference_doc.reference_doctype, reference_doc.reference_docname
if doc.reference_type == "CRM Task":
reference_doc = frappe.get_doc(doc.reference_type, doc.reference_name)
return reference_doc.reference_doctype, reference_doc.reference_docname
return doc.reference_type, doc.reference_name
return doc.reference_type, doc.reference_name

View File

@ -30,25 +30,27 @@ def notify_agent(doc):
if doctype.startswith("CRM "):
doctype = doctype[4:].lower()
notification_text = f"""
<div class="mb-2 leading-5 text-gray-600">
<span class="font-medium text-gray-900">{ _('You') }</span>
<div class="mb-2 leading-5 text-ink-gray-5">
<span class="font-medium text-ink-gray-9">{ _('You') }</span>
<span>{ _('received a whatsapp message in {0}').format(doctype) }</span>
<span class="font-medium text-gray-900">{ doc.reference_name }</span>
<span class="font-medium text-ink-gray-9">{ doc.reference_name }</span>
</div>
"""
assigned_users = get_assigned_users(doc.reference_doctype, doc.reference_name)
for user in assigned_users:
notify_user({
"owner": doc.owner,
"assigned_to": user,
"notification_type": "WhatsApp",
"message": doc.message,
"notification_text": notification_text,
"reference_doctype": "WhatsApp Message",
"reference_docname": doc.name,
"redirect_to_doctype": doc.reference_doctype,
"redirect_to_docname": doc.reference_name,
})
notify_user(
{
"owner": doc.owner,
"assigned_to": user,
"notification_type": "WhatsApp",
"message": doc.message,
"notification_text": notification_text,
"reference_doctype": "WhatsApp Message",
"reference_docname": doc.name,
"redirect_to_doctype": doc.reference_doctype,
"redirect_to_docname": doc.reference_name,
}
)
def get_lead_or_deal_from_number(number):
@ -92,6 +94,7 @@ def is_whatsapp_enabled():
return False
return frappe.get_cached_value("WhatsApp Settings", "WhatsApp Settings", "enabled")
@frappe.whitelist()
def is_whatsapp_installed():
if not frappe.db.exists("DocType", "WhatsApp Settings"):
@ -105,8 +108,8 @@ def get_whatsapp_messages(reference_doctype, reference_name):
return []
messages = []
if reference_doctype == 'CRM Deal':
lead = frappe.db.get_value(reference_doctype, reference_name, 'lead')
if reference_doctype == "CRM Deal":
lead = frappe.db.get_value(reference_doctype, reference_name, "lead")
if lead:
messages = frappe.get_all(
"WhatsApp Message",

@ -1 +1 @@
Subproject commit 59415754663693989ae5144b43370f4b0426aa50
Subproject commit 82150c9591a36abc5dc8667ae5873651d4b2cc0d

View File

@ -18,7 +18,7 @@
/>
<component
v-else
class="size-4"
class="size-4 text-ink-gray-7"
:is="fileIcon(attachment.file_type)"
/>
</div>

View File

@ -25,7 +25,7 @@
</div>
</div>
<div
class="flex flex-col gap-2 border border-outline-gray-modals rounded-md bg-surface-white px-3 py-2.5"
class="flex flex-col gap-2 border border-outline-gray-modals rounded-md bg-surface-white px-3 py-2.5 text-ink-gray-9"
>
<div class="flex items-center justify-between">
<div class="inline-flex gap-2 items-center text-base font-medium">

View File

@ -20,7 +20,7 @@
</div>
</div>
<div
class="cursor-pointer rounded bg-surface-menu-bar px-3 py-[7.5px] text-base leading-6 transition-all duration-300 ease-in-out"
class="cursor-pointer rounded bg-surface-gray-1 px-3 py-[7.5px] text-base leading-6 transition-all duration-300 ease-in-out"
>
<div class="prose-f" v-html="activity.content" />
<div v-if="activity.attachments.length" class="mt-2 flex flex-wrap gap-2">

View File

@ -2,7 +2,7 @@
<div
class="cursor-pointer flex flex-col rounded-md shadow bg-surface-white px-3 py-1.5 text-base transition-all duration-300 ease-in-out"
>
<div class="-mb-0.5 flex items-center justify-between gap-2 truncate">
<div class="-mb-0.5 flex items-center justify-between gap-2 truncate text-ink-gray-9">
<div class="flex items-center gap-2 truncate">
<span>{{ activity.data.sender_full_name }}</span>
<span class="sm:flex hidden text-sm text-ink-gray-5">

View File

@ -2,7 +2,7 @@
<div v-if="tasks.length">
<div v-for="(task, i) in tasks" :key="task.name">
<div
class="activity flex cursor-pointer gap-6 rounded p-2.5 duration-300 ease-in-out hover:bg-surface-menu-bar"
class="activity flex cursor-pointer gap-6 rounded p-2.5 duration-300 ease-in-out hover:bg-surface-gray-1"
@click="modalRef.showTask(task)"
>
<div class="flex flex-1 flex-col gap-1.5 text-base truncate">
@ -76,7 +76,7 @@
<Button
icon="more-horizontal"
variant="ghosted"
class="hover:bg-surface-gray-4"
class="hover:bg-surface-gray-4 text-ink-gray-9"
/>
</Dropdown>
</div>

View File

@ -11,7 +11,7 @@
>
<div
:id="whatsapp.name"
class="group/message relative max-w-[90%] rounded-md bg-surface-menu-bar p-1.5 pl-2 text-base shadow-sm"
class="group/message relative max-w-[90%] rounded-md bg-surface-gray-1 text-ink-gray-9 p-1.5 pl-2 text-base shadow-sm"
>
<div
v-if="whatsapp.is_reply"

View File

@ -3,7 +3,7 @@
<template #target="{ togglePopover }">
<button
:class="[
active ? 'bg-surface-gray-2' : 'text-ink-gray-8',
active ? 'bg-surface-gray-3' : 'text-ink-gray-6',
'group w-full flex h-7 items-center justify-between rounded px-2 text-base hover:bg-surface-gray-2',
]"
@click.prevent="togglePopover()"
@ -19,7 +19,7 @@
</template>
<template #body>
<div
class="grid grid-cols-3 justify-between mx-3 p-2 rounded-lg border border-gray-100 bg-surface-white shadow-xl"
class="grid grid-cols-3 justify-between mx-3 p-2 min-w-40 rounded-lg bg-surface-modal shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div v-for="app in apps.data" :key="app.name">
<a
@ -39,8 +39,8 @@
<script setup>
import AppsIcon from '@/components/Icons/AppsIcon.vue'
import { Popover, createResource } from 'frappe-ui'
import { onUnmounted } from 'vue';
import { stopRecording } from '@/telemetry';
import { onUnmounted } from 'vue'
import { stopRecording } from '@/telemetry'
const props = defineProps({
active: Boolean,

View File

@ -12,7 +12,7 @@
</template>
<template #body="{ close }">
<div
class="my-2 rounded-lg border border-gray-100 bg-surface-white p-1.5 shadow-xl"
class="my-2 p-1.5 min-w-40 rounded-lg bg-surface-modal shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div v-if="!edit">
<Draggable
@ -49,7 +49,7 @@
</div>
</template>
</Draggable>
<div class="mt-1.5 flex flex-col gap-1 border-t pt-1.5">
<div class="mt-1.5 flex flex-col gap-1 border-t border-outline-gray-modals pt-1.5">
<Autocomplete
value=""
:options="fields"
@ -114,7 +114,7 @@
placeholder="10rem"
:description="
__(
'Width can be in number, pixel or rem (eg. 3, 30px, 10rem)'
'Width can be in number, pixel or rem (eg. 3, 30px, 10rem)',
)
"
:debounce="500"
@ -295,6 +295,6 @@ watchOnce(
oldValues.value.columns = JSON.parse(JSON.stringify(val.columns))
oldValues.value.rows = JSON.parse(JSON.stringify(val.rows))
oldValues.value.isDefault = val.is_default
}
},
)
</script>

View File

@ -1,7 +1,7 @@
<template>
<div>
<div
class="flex flex-wrap gap-1 min-h-20 p-1.5 cursor-text rounded h-7 text-base border border-outline-gray-2 bg-surface-white hover:border-outline-gray-3 focus:border-outline-gray-4 focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3 text-ink-gray-8 transition-colors w-full"
class="group flex flex-wrap gap-1 min-h-20 p-1.5 cursor-text rounded h-7 text-base bg-surface-gray-2 hover:bg-surface-gray-3 focus:border-outline-gray-4 focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3 text-ink-gray-8 transition-colors w-full"
@click="setFocus"
>
<Button
@ -11,7 +11,7 @@
:label="value"
theme="gray"
variant="subtle"
class="rounded"
class="rounded bg-surface-gray-3 group-hover:bg-surface-gray-4 focus-visible:ring-outline-gray-4"
@keydown.delete.capture.stop="removeLastValue"
>
<template #suffix>
@ -23,9 +23,9 @@
</template>
</Button>
<div class="flex-1">
<TextInput
<input
ref="search"
class="w-full border-none bg-surface-white hover:bg-surface-white focus:border-none focus:!shadow-none focus-visible:!ring-0"
class="w-full border-none h-7 text-base bg-surface-gray-2 group-hover:bg-surface-gray-3 focus:border-none focus:!shadow-none focus-visible:!ring-0 transition-colors"
type="text"
v-model="query"
placeholder="example@email.com"
@ -113,7 +113,7 @@ const removeLastValue = () => {
}
function setFocus() {
search.value.el.focus()
search.value.focus()
}
defineExpose({ setFocus })

View File

@ -41,9 +41,11 @@
</template>
<template #body="{ isOpen }">
<div v-show="isOpen">
<div class="mt-1 rounded-lg bg-surface-white py-1 text-base shadow-2xl">
<div
class="mt-1 rounded-lg bg-surface-modal shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<ComboboxOptions
class="my-1 max-h-[12rem] overflow-y-auto px-1.5"
class="p-1.5 max-h-[12rem] overflow-y-auto"
static
>
<ComboboxOption
@ -55,7 +57,7 @@
<li
:class="[
'flex cursor-pointer items-center rounded px-2 py-1 text-base',
{ 'bg-surface-gray-2': active },
{ 'bg-surface-gray-3': active },
]"
>
<UserAvatar
@ -146,16 +148,15 @@ const filterOptions = createResource({
cache: [text.value, 'Contact'],
params: { txt: text.value },
transform: (data) => {
let allData = data
.map((option) => {
let fullName = option[0]
let email = option[1]
let name = option[2]
return {
label: fullName || name || email,
value: email,
}
})
let allData = data.map((option) => {
let fullName = option[0]
let email = option[1]
let name = option[2]
return {
label: fullName || name || email,
value: email,
}
})
return allData
},
})

View File

@ -61,7 +61,7 @@
</div>
</div>
<div v-if="option.selected">
<FeatherIcon name="check" class="text-primary-500 h-4 w-6" size="sm" />
<FeatherIcon name="check" class="text-ink-gray-5 h-4 w-6" size="sm" />
</div>
</div>
</template>

View File

@ -34,7 +34,9 @@
variant="ghost"
@click="toggleCC()"
:class="[
cc ? '!bg-surface-gray-4 hover:bg-surface-gray-3' : '!text-ink-gray-4',
cc
? '!bg-surface-gray-4 hover:bg-surface-gray-3'
: '!text-ink-gray-4',
]"
/>
<Button
@ -42,7 +44,9 @@
variant="ghost"
@click="toggleBCC()"
:class="[
bcc ? '!bg-surface-gray-4 hover:bg-surface-gray-3' : '!text-ink-gray-4',
bcc
? '!bg-surface-gray-4 hover:bg-surface-gray-3'
: '!text-ink-gray-4',
]"
/>
</div>
@ -73,8 +77,8 @@
</div>
<div class="sm:mx-10 mx-4 flex items-center gap-2 pb-2.5">
<span class="text-xs text-ink-gray-4">{{ __('SUBJECT') }}:</span>
<TextInput
class="flex-1 border-none bg-surface-white hover:bg-surface-white focus:border-none focus:!shadow-none focus-visible:!ring-0"
<input
class="flex-1 border-none text-ink-gray-9 text-base bg-surface-white hover:bg-surface-white focus:border-none focus:!shadow-none focus-visible:!ring-0"
v-model="subject"
/>
</div>

View File

@ -3,7 +3,7 @@
<div
v-for="section in sections"
:key="section.label"
class="section first:border-t-0 first:pt-0"
class="section first:border-t-0 border-outline-gray-modals first:pt-0"
:class="section.hideBorder ? '' : 'border-t pt-4'"
>
<div

View File

@ -9,7 +9,7 @@
<template #prefix><FilterIcon class="h-4" /></template>
<template v-if="filters?.size" #suffix>
<div
class="flex h-5 w-5 items-center justify-center rounded bg-surface-gray-7 pt-[1px] text-2xs font-medium text-ink-white"
class="flex h-5 w-5 items-center justify-center rounded-[5px] bg-surface-white pt-px text-xs font-medium text-ink-gray-8 shadow-sm"
>
{{ filters.size }}
</div>
@ -27,7 +27,9 @@
</div>
</template>
<template #body="{ close }">
<div class="my-2 rounded-lg border border-gray-100 bg-surface-white shadow-xl">
<div
class="my-2 min-w-40 rounded-lg bg-surface-modal shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div class="min-w-72 p-2 sm:min-w-[400px]">
<div
v-if="filters?.size"

View File

@ -8,10 +8,10 @@
<template #body="{ togglePopover }">
<div
v-if="reaction"
class="flex items-center justify-center gap-2 rounded-full bg-surface-white px-2 py-1 shadow-sm"
class="px-2 py-1 flex items-center justify-center gap-2 rounded-full bg-surface-modal shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div
class="size-5 cursor-pointer rounded-full bg-surface-white text-xl"
class="size-5 cursor-pointer rounded-full bg-surface-transparent text-xl"
v-for="r in reactionEmojis"
:key="r"
@click="() => (emoji = r) && togglePopover()"
@ -26,9 +26,12 @@
@click.stop="() => (reaction = false)"
/>
</div>
<div v-else class="my-3 max-w-max transform bg-surface-white px-4 sm:px-0">
<div
v-else
class="my-3 max-w-max transform bg-surface-white px-4 sm:px-0"
>
<div
class="relative max-h-96 overflow-y-auto rounded-lg pb-3 shadow-2xl ring-1 ring-black ring-opacity-5"
class="relative max-h-96 pb-3 overflow-y-auto min-w-40 rounded-lg bg-surface-modal shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div class="flex gap-2 px-3 pb-1 pt-3">
<div class="flex-1">
@ -43,7 +46,9 @@
</div>
<div class="w-96"></div>
<div class="px-3" v-for="(emojis, group) in emojiGroups" :key="group">
<div class="sticky top-0 bg-surface-white pb-2 pt-3 text-sm text-ink-gray-7">
<div
class="sticky top-0 bg-surface-modal pb-2 pt-3 text-sm text-ink-gray-7"
>
{{ group }}
</div>
<div class="grid w-96 grid-cols-12 place-items-center">

View File

@ -1,31 +1,16 @@
<template>
<svg
width="16"
height="17"
viewBox="0 0 16 17"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M2 4.5H14"
stroke="currentColor"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M4 8.5H12"
stroke="currentColor"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M6.5 12.5H9.5"
stroke="currentColor"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
fill-rule="evenodd"
clip-rule="evenodd"
d="M2 4.16675C1.72386 4.16675 1.5 4.39061 1.5 4.66675C1.5 4.94289 1.72386 5.16675 2 5.16675H14C14.2761 5.16675 14.5 4.94289 14.5 4.66675C14.5 4.39061 14.2761 4.16675 14 4.16675H2ZM3.49996 7.99761C3.49996 7.72147 3.72382 7.49761 3.99996 7.49761H12C12.2761 7.49761 12.5 7.72147 12.5 7.99761C12.5 8.27375 12.2761 8.49761 12 8.49761H3.99996C3.72382 8.49761 3.49996 8.27375 3.49996 7.99761ZM5.9 11.3289C5.9 11.0527 6.12386 10.8289 6.4 10.8289H9.6C9.87614 10.8289 10.1 11.0527 10.1 11.3289C10.1 11.605 9.87614 11.8289 9.6 11.8289H6.4C6.12386 11.8289 5.9 11.605 5.9 11.3289Z"
fill="currentColor"
/>
</svg>
</template>

View File

@ -1,45 +1,16 @@
<template>
<svg
width="16"
height="17"
viewBox="0 0 16 17"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1.75 3.75H10.75"
stroke="currentColor"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M1.75 7.75H7.75"
stroke="currentColor"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M1.75 11.75H5.75"
stroke="currentColor"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M14.25 8.25L12.25 6.25L10.25 8.25"
stroke="currentColor"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M12.25 12.25L12.25 6.25"
stroke="currentColor"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
fill-rule="evenodd"
clip-rule="evenodd"
d="M5.5 3.5C5.5 3.22386 5.27614 3 5 3C4.72386 3 4.5 3.22386 4.5 3.5V11.2931L2.87846 9.67159C2.68319 9.47633 2.36661 9.47633 2.17135 9.67159C1.97609 9.86686 1.97609 10.1834 2.17135 10.3787L4.64622 12.8536C4.75097 12.9583 4.89063 13.0069 5.02774 12.9992C5.15903 12.9921 5.27684 12.9342 5.36195 12.845L7.8282 10.3787C8.02347 10.1834 8.02347 9.86686 7.8282 9.67159C7.63294 9.47633 7.31636 9.47633 7.1211 9.67159L5.5 11.2927V3.5ZM11.3698 3.16295C11.2784 3.06282 11.1468 3 11.0005 3C10.9947 3 10.989 3.0001 10.9832 3.00029C10.8608 3.00432 10.7396 3.05304 10.6462 3.14647L8.17135 5.62134C7.97609 5.8166 7.97609 6.13319 8.17135 6.32845C8.36661 6.52371 8.68319 6.52371 8.87846 6.32845L10.5005 4.70641V12.5C10.5005 12.7761 10.7243 13 11.0005 13C11.2766 13 11.5005 12.7761 11.5005 12.5V4.70784L13.1211 6.32845C13.3164 6.52371 13.6329 6.52371 13.8282 6.32845C14.0235 6.13319 14.0235 5.8166 13.8282 5.62134L11.3698 3.16295Z"
fill="currentColor"
/>
</svg>
</template>

View File

@ -19,7 +19,7 @@
rx="1"
transform="rotate(-45 0.792893 0)"
fill="currentColor"
stroke="white"
class="stroke stroke-ink-white"
/>
</svg>
</template>

View File

@ -11,7 +11,9 @@
<Dialog v-model="showDialog" :options="{ title: __('Kanban Settings') }">
<template #body-content>
<div>
<div class="text-base text-ink-gray-8 mb-2">{{ __('Column Field') }}</div>
<div class="text-base text-ink-gray-8 mb-2">
{{ __('Column Field') }}
</div>
<Autocomplete
v-if="columnFields"
value=""
@ -21,7 +23,6 @@
<template #target="{ togglePopover }">
<Button
class="w-full !justify-start"
variant="subtle"
@click="togglePopover()"
:label="columnField.label"
/>
@ -39,7 +40,6 @@
<template #target="{ togglePopover }">
<Button
class="w-full !justify-start"
variant="subtle"
@click="togglePopover()"
:label="titleField.label"
/>
@ -47,7 +47,9 @@
</Autocomplete>
</div>
<div class="mt-4">
<div class="text-base text-ink-gray-8 mb-2">{{ __('Fields Order') }}</div>
<div class="text-base text-ink-gray-8 mb-2">
{{ __('Fields Order') }}
</div>
<Draggable
:list="allFields"
@end="reorder"
@ -57,7 +59,7 @@
>
<template #item="{ element: field }">
<div
class="px-1 py-0.5 border rounded text-base text-ink-gray-8 flex items-center justify-between gap-2"
class="px-1 py-0.5 border border-outline-gray-modals rounded text-base text-ink-gray-8 flex items-center justify-between gap-2"
>
<div class="flex items-center gap-2">
<DragVerticalIcon class="h-3.5 cursor-grab" />
@ -78,7 +80,6 @@
<template #target="{ togglePopover }">
<Button
class="w-full mt-2"
variant="outline"
@click="togglePopover()"
:label="__('Add Field')"
>

View File

@ -17,7 +17,11 @@
<div class="flex items-center text-base">
<NestedPopover>
<template #target>
<Button variant="ghost" size="sm" class="hover:!bg-surface-gray-2">
<Button
variant="ghost"
size="sm"
class="hover:!bg-surface-gray-2"
>
<IndicatorIcon
:class="colorClasses(column.column.color, true)"
/>
@ -25,7 +29,7 @@
</template>
<template #body="{ close }">
<div
class="flex flex-col gap-3 px-3 py-2.5 rounded-lg border border-gray-100 bg-surface-white shadow-xl"
class="flex flex-col gap-3 px-3 py-2.5 min-w-40 rounded-lg bg-surface-modal shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div class="flex gap-1">
<Button
@ -48,7 +52,7 @@
</div>
</template>
</NestedPopover>
<div>{{ column.column.name }}</div>
<div class="text-ink-gray-9">{{ column.column.name }}</div>
</div>
<div class="flex">
<Dropdown :options="actions(column)">
@ -80,7 +84,7 @@
<template #item="{ element: fields }">
<component
:is="options.getRoute ? 'router-link' : 'div'"
class="pt-3 px-3.5 pb-2.5 rounded-lg border bg-surface-white text-base flex flex-col"
class="pt-3 px-3.5 pb-2.5 rounded-lg border bg-surface-white text-base flex flex-col text-ink-gray-9"
:data-name="fields.name"
v-bind="{
to: options.getRoute ? options.getRoute(fields) : undefined,

View File

@ -1,7 +1,7 @@
<template>
<div class="flex h-screen w-screen">
<MobileSidebar />
<div class="flex h-full flex-1 flex-col overflow-auto">
<div class="flex h-full flex-1 flex-col overflow-auto bg-surface-white">
<MobileAppHeader />
<slot />
</div>

View File

@ -6,7 +6,7 @@
variant="ghosted"
@click="sidebarOpened = !sidebarOpened"
>
<MenuIcon class="h-4" />
<MenuIcon class="h-4 text-ink-gray-9" />
</Button>
</div>
<div id="app-header" class="flex-1" />

View File

@ -1,7 +1,7 @@
<template>
<Dialog v-model="show" :options="dialogOptions">
<template #body>
<div class="bg-surface-white px-4 pb-6 pt-5 sm:px-6">
<div class="bg-surface-modal px-4 pb-6 pt-5 sm:px-6">
<div class="mb-5 flex items-center justify-between">
<div>
<h3 class="text-2xl font-semibold leading-6 text-ink-gray-9">

View File

@ -40,7 +40,7 @@
</template>
<template #item-label="{ option }">
<Tooltip :text="option.value">
<div class="cursor-pointer">
<div class="cursor-pointer text-ink-gray-9">
{{ getUser(option.value).full_name }}
</div>
</Tooltip>
@ -55,7 +55,6 @@
<Button
:label="getUser(assignee.name).full_name"
theme="gray"
variant="outline"
>
<template #prefix>
<UserAvatar :user="assignee.name" size="sm" />

View File

@ -1,7 +1,7 @@
<template>
<Dialog v-model="show" :options="dialogOptions">
<template #body>
<div class="bg-surface-white px-4 pb-6 pt-5 sm:px-6">
<div class="bg-surface-modal px-4 pb-6 pt-5 sm:px-6">
<div class="mb-5 flex items-center justify-between">
<div>
<h3 class="text-2xl font-semibold leading-6 text-ink-gray-9">

View File

@ -1,7 +1,7 @@
<template>
<Dialog v-model="show" :options="{ size: '3xl' }">
<template #body>
<div class="bg-surface-white px-4 pb-6 pt-5 sm:px-6">
<div class="bg-surface-modal px-4 pb-6 pt-5 sm:px-6">
<div class="mb-5 flex items-center justify-between">
<div>
<h3 class="text-2xl font-semibold leading-6 text-ink-gray-9">

View File

@ -17,60 +17,49 @@
<div class="flex flex-col gap-4">
<div class="flex sm:flex-row flex-col gap-4">
<div class="flex-1">
<div class="mb-1.5 text-sm text-ink-gray-5">
{{ __('Name') }}
<span class="text-ink-red-3">*</span>
</div>
<TextInput
<FormControl
ref="nameRef"
variant="outline"
v-model="_emailTemplate.name"
:placeholder="__('Payment Reminder')"
:label="__('Name')"
:required="true"
/>
</div>
<div class="flex-1">
<div class="mb-1.5 text-sm text-ink-gray-5">{{ __('Doctype') }}</div>
<Select
variant="outline"
<FormControl
type="select"
v-model="_emailTemplate.reference_doctype"
:label="__('Doctype')"
:options="['CRM Deal', 'CRM Lead']"
:placeholder="__('CRM Deal')"
/>
</div>
</div>
<div>
<div class="mb-1.5 text-sm text-ink-gray-5">
{{ __('Subject') }}
<span class="text-ink-red-3">*</span>
</div>
<TextInput
<FormControl
ref="subjectRef"
variant="outline"
v-model="_emailTemplate.subject"
:label="__('Subject')"
:placeholder="__('Payment Reminder from Frappé - (#{{ name }})')"
:required="true"
/>
</div>
<div>
<div class="mb-1.5 text-sm text-ink-gray-5">
{{ __('Content Type') }}
</div>
<Select
variant="outline"
<FormControl
type="select"
v-model="_emailTemplate.content_type"
:label="__('Content Type')"
default="Rich Text"
:options="['Rich Text', 'HTML']"
:placeholder="__('Rich Text')"
/>
</div>
<div>
<div class="mb-1.5 text-sm text-ink-gray-5">
{{ __('Content') }}
<span class="text-ink-red-3">*</span>
</div>
<FormControl
v-if="_emailTemplate.content_type === 'HTML'"
type="textarea"
variant="outline"
:label="__('Content')"
:required="true"
ref="content"
:rows="10"
v-model="_emailTemplate.response_html"
@ -80,20 +69,24 @@
)
"
/>
<TextEditor
v-else
variant="outline"
ref="content"
editor-class="!prose-sm overflow-auto min-h-[180px] max-h-80 py-1.5 px-2 rounded border border-outline-gray-2 bg-surface-white hover:border-outline-gray-3 hover:shadow-sm focus:bg-surface-white focus:border-outline-gray-4 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3 text-ink-gray-8 transition-colors"
:bubbleMenu="true"
:content="_emailTemplate.response"
@change="(val) => (_emailTemplate.response = val)"
:placeholder="
__(
'Dear {{ lead_name }}, \n\nThis is a reminder for the payment of {{ grand_total }}. \n\nThanks, \nFrappé',
)
"
/>
<div v-else>
<div class="mb-1.5 text-xs text-ink-gray-5">
{{ __('Content') }}
<span class="text-ink-red-3">*</span>
</div>
<TextEditor
ref="content"
editor-class="!prose-sm overflow-auto min-h-[180px] max-h-80 py-1.5 px-2 rounded border border-[--surface-gray-2] bg-surface-gray-2 placeholder-ink-gray-4 hover:border-outline-gray-modals hover:bg-surface-gray-3 hover:shadow-sm focus:bg-surface-white focus:border-outline-gray-4 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3 text-ink-gray-8 transition-colors"
:bubbleMenu="true"
:content="_emailTemplate.response"
@change="(val) => (_emailTemplate.response = val)"
:placeholder="
__(
'Dear {{ lead_name }}, \n\nThis is a reminder for the payment of {{ grand_total }}. \n\nThanks, \nFrappé',
)
"
/>
</div>
</div>
<div>
<Checkbox v-model="_emailTemplate.enabled" :label="__('Enabled')" />
@ -106,7 +99,7 @@
<script setup>
import { capture } from '@/telemetry'
import { Checkbox, Select, TextEditor, call } from 'frappe-ui'
import { Checkbox, TextEditor, call } from 'frappe-ui'
import { ref, nextTick, watch } from 'vue'
const props = defineProps({
@ -229,9 +222,9 @@ watch(
errorMessage.value = ''
nextTick(() => {
if (_emailTemplate.value.name) {
subjectRef.value.el.focus()
subjectRef.value?.el?.focus()
} else {
nameRef.value.el.focus()
nameRef.value?.el?.focus()
}
_emailTemplate.value = { ...props.emailTemplate }
_emailTemplate.value.content_type = _emailTemplate.value.use_html

View File

@ -1,7 +1,7 @@
<template>
<Dialog v-model="show" :options="{ size: '3xl' }">
<template #body>
<div class="bg-surface-white px-4 pb-6 pt-5 sm:px-6">
<div class="bg-surface-modal px-4 pb-6 pt-5 sm:px-6">
<div class="mb-5 flex items-center justify-between">
<div>
<h3 class="text-2xl font-semibold leading-6 text-ink-gray-9">

View File

@ -19,7 +19,6 @@
</h3>
<Button
v-if="_note?.reference_docname"
variant="outline"
size="sm"
:label="
_note.reference_doctype == 'CRM Deal'
@ -37,20 +36,19 @@
<template #body-content>
<div class="flex flex-col gap-4">
<div>
<div class="mb-1.5 text-sm text-ink-gray-5">{{ __('Title') }}</div>
<TextInput
<FormControl
ref="title"
variant="outline"
:label="__('Title')"
v-model="_note.title"
:placeholder="__('Call with John Doe')"
/>
</div>
<div>
<div class="mb-1.5 text-sm text-ink-gray-5">{{ __('Content') }}</div>
<div class="mb-1.5 text-xs text-ink-gray-5">{{ __('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-outline-gray-2 bg-surface-white hover:border-outline-gray-3 hover:shadow-sm focus:bg-surface-white focus:border-outline-gray-4 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3 text-ink-gray-8 transition-colors"
editor-class="!prose-sm overflow-auto min-h-[180px] max-h-80 py-1.5 px-2 rounded border border-[--surface-gray-2] bg-surface-gray-2 placeholder-ink-gray-4 hover:border-outline-gray-modals hover:bg-surface-gray-3 hover:shadow-sm focus:bg-surface-white focus:border-outline-gray-4 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3 text-ink-gray-8 transition-colors"
:bubbleMenu="true"
:content="_note.content"
@change="(val) => (_note.content = val)"
@ -149,12 +147,12 @@ watch(
if (!value) return
editMode.value = false
nextTick(() => {
title.value.el.focus()
title.value?.el?.focus()
_note.value = { ...props.note }
if (_note.value.title || _note.value.content) {
editMode.value = true
}
})
}
},
)
</script>

View File

@ -1,7 +1,7 @@
<template>
<Dialog v-model="show" :options="dialogOptions">
<template #body>
<div class="bg-surface-white px-4 pb-6 pt-5 sm:px-6">
<div class="bg-surface-modal px-4 pb-6 pt-5 sm:px-6">
<div class="mb-5 flex items-center justify-between">
<div>
<h3 class="text-2xl font-semibold leading-6 text-ink-gray-9">

View File

@ -19,7 +19,6 @@
</h3>
<Button
v-if="task?.reference_docname"
variant="outline"
size="sm"
:label="
task.reference_doctype == 'CRM Deal'
@ -37,22 +36,21 @@
<template #body-content>
<div class="flex flex-col gap-4">
<div>
<div class="mb-1.5 text-sm text-ink-gray-5">{{ __('Title') }}</div>
<TextInput
<FormControl
ref="title"
variant="outline"
:label="__('Title')"
v-model="_task.title"
:placeholder="__('Call with John Doe')"
/>
</div>
<div>
<div class="mb-1.5 text-sm text-ink-gray-5">
<div class="mb-1.5 text-xs text-ink-gray-5">
{{ __('Description') }}
</div>
<TextEditor
variant="outline"
ref="description"
editor-class="!prose-sm overflow-auto min-h-[80px] max-h-80 py-1.5 px-2 rounded border border-outline-gray-2 bg-surface-white hover:border-outline-gray-3 hover:shadow-sm focus:bg-surface-white focus:border-outline-gray-4 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3 text-ink-gray-8 transition-colors"
editor-class="!prose-sm overflow-auto min-h-[180px] max-h-80 py-1.5 px-2 rounded border border-[--surface-gray-2] bg-surface-gray-2 placeholder-ink-gray-4 hover:border-outline-gray-modals hover:bg-surface-gray-3 hover:shadow-sm focus:bg-surface-white focus:border-outline-gray-4 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3 text-ink-gray-8 transition-colors"
:bubbleMenu="true"
:content="_task.description"
@change="(val) => (_task.description = val)"

View File

@ -5,15 +5,15 @@
title: editMode
? __('Edit View')
: duplicateMode
? __('Duplicate View')
: __('Create View'),
? __('Duplicate View')
: __('Create View'),
actions: [
{
label: editMode
? __('Save Changes')
: duplicateMode
? __('Duplicate')
: __('Create'),
? __('Duplicate')
: __('Create'),
variant: 'solid',
onClick: () => (editMode ? update() : create()),
},
@ -27,16 +27,14 @@
<div class="flex gap-2">
<IconPicker v-model="view.icon" v-slot="{ togglePopover }">
<Button
variant="outline"
size="md"
class="flex size-8 text-2xl leading-none"
:label="view.icon"
@click="togglePopover"
/>
</IconPicker>
<TextInput
<FormControl
class="flex-1"
variant="outline"
size="md"
type="text"
:placeholder="__('My Open Deals')"
@ -49,7 +47,7 @@
<script setup>
import IconPicker from '@/components/IconPicker.vue'
import { call, TextInput } from 'frappe-ui'
import { call } from 'frappe-ui'
import { ref, watch, nextTick } from 'vue'
const props = defineProps({
@ -87,7 +85,7 @@ async function create() {
view.value.doctype = props.doctype
let v = await call(
'crm.fcrm.doctype.crm_view_settings.crm_view_settings.create',
{ view: view.value }
{ view: view.value },
)
show.value = false
props.options.afterCreate?.(v)

View File

@ -1,7 +1,7 @@
<template>
<div
v-if="avatars?.length"
class="mr-1.5 flex cursor-pointer items-center"
class="mr-1.5 flex cursor-pointer items-center "
:class="[
avatars?.length > 1 ? 'flex-row-reverse' : 'truncate [&>div]:truncate',
]"
@ -24,7 +24,7 @@
:key="avatar.name"
>
<Avatar
class="user-avatar -mr-1.5 transform ring-2 ring-white transition hover:z-10 hover:scale-110"
class="user-avatar -mr-1.5 transform ring-2 ring-outline-white transition hover:z-10 hover:scale-110"
shape="circle"
:image="avatar.image"
:label="avatar.label"

View File

@ -10,7 +10,7 @@
left: 'calc(100% + 1px)',
}"
>
<div class="flex h-screen flex-col">
<div class="flex h-screen flex-col text-ink-gray-9">
<div
class="z-20 flex items-center justify-between border-b bg-surface-white px-5 py-2.5"
>
@ -38,7 +38,7 @@
</div>
<div
v-if="notifications.data?.length"
class="divide-y overflow-auto text-base"
class="divide-y divide-outline-gray-modals overflow-auto text-base"
>
<RouterLink
v-for="n in notifications.data"

View File

@ -2,14 +2,14 @@
<div>
<Draggable :list="sections" item-key="label" class="flex flex-col gap-5.5">
<template #item="{ element: section }">
<div class="flex flex-col gap-1.5 p-2.5 bg-surface-menu-bar rounded">
<div class="flex flex-col gap-1.5 p-2.5 bg-surface-gray-2 rounded">
<div class="flex items-center justify-between">
<div
class="flex h-7 max-w-fit cursor-pointer items-center gap-2 text-base font-medium leading-4"
class="flex h-7 max-w-fit cursor-pointer items-center gap-2 text-base font-medium leading-4 text-ink-gray-9"
>
<div
v-if="!section.editingLabel"
:class="section.hideLabel ? 'text-ink-gray-3' : ''"
:class="{ 'text-ink-gray-3': section.hideLabel }"
>
{{ __(section.label) || __('Untitled') }}
</div>
@ -48,7 +48,7 @@
>
<template #item="{ element: field }">
<div
class="px-2.5 py-2 border rounded text-base bg-surface-white text-ink-gray-8 flex items-center leading-4 justify-between gap-2"
class="px-2.5 py-2 border border-outline-gray-2 rounded text-base bg-surface-modal text-ink-gray-8 flex items-center leading-4 justify-between gap-2"
>
<div class="flex items-center gap-2">
<DragVerticalIcon class="h-3.5 cursor-grab" />
@ -74,7 +74,7 @@
<template #target="{ togglePopover }">
<div class="gap-2 w-full">
<Button
class="w-full !h-8 !border-outline-gray-modals hover:!border-outline-gray-2"
class="w-full !h-8 !bg-surface-modal"
variant="outline"
@click="togglePopover()"
:label="__('Add Field')"
@ -86,7 +86,7 @@
</div>
</template>
<template #item-label="{ option }">
<div class="flex flex-col gap-1">
<div class="flex flex-col gap-1 text-ink-gray-9">
<div>{{ option.label }}</div>
<div class="text-ink-gray-4 text-sm">
{{ `${option.fieldname} - ${option.fieldtype}` }}

View File

@ -112,6 +112,6 @@ let slaSection = computed(() => {
<style scoped>
:deep(.form-control button) {
border-color: transparent;
background: white;
background: transparent;
}
</style>

View File

@ -2,12 +2,12 @@
<slot name="header" v-bind="{ opened, hide, open, close, toggle }">
<div v-if="!hide" class="flex items-center justify-between">
<div
class="flex h-7 max-w-fit cursor-pointer items-center gap-2 pl-2 pr-3 text-base font-semibold leading-5"
class="flex h-7 text-ink-gray-9 max-w-fit cursor-pointer items-center gap-2 pl-2 pr-3 text-base font-semibold leading-5"
@click="toggle()"
>
<FeatherIcon
name="chevron-right"
class="h-4 text-ink-gray-9 transition-all duration-300 ease-in-out"
class="h-4 transition-all duration-300 ease-in-out"
:class="{ 'rotate-90': opened }"
/>
{{ __(label) || __('Untitled') }}

View File

@ -39,7 +39,10 @@
<div v-if="data[field.name]" class="truncate">
{{ data[field.name] }}
</div>
<div v-else class="text-base leading-5 text-ink-gray-4 truncate">
<div
v-else
class="text-base leading-5 text-ink-gray-4 truncate"
>
{{ field.placeholder }}
</div>
<template #suffix>
@ -52,7 +55,7 @@
</template>
<template #body>
<div
class="my-2 space-y-1.5 divide-y rounded-lg border border-gray-100 bg-surface-white p-1.5 shadow-xl"
class="my-2 p-1.5 min-w-40 space-y-1.5 divide-y divide-outline-gray-1 rounded-lg bg-surface-modal shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div>
<DropdownItem
@ -161,16 +164,18 @@
@change.stop="emit('update', field.name, $event.target.value)"
/>
</div>
<ArrowUpRightIcon
v-if="field.type === 'link' && field.link && data[field.name]"
class="h-4 w-4 shrink-0 cursor-pointer text-ink-gray-5 hover:text-ink-gray-8"
@click="field.link(data[field.name])"
/>
<EditIcon
v-if="field.type === 'link' && field.edit && data[field.name]"
class="size-3.5 shrink-0 cursor-pointer text-ink-gray-5 hover:text-ink-gray-8"
@click="field.edit(data[field.name])"
/>
<div class="ml-1">
<ArrowUpRightIcon
v-if="field.type === 'link' && field.link && data[field.name]"
class="h-4 w-4 shrink-0 cursor-pointer text-ink-gray-5 hover:text-ink-gray-8"
@click.stop="field.link(data[field.name])"
/>
<EditIcon
v-if="field.type === 'link' && field.edit && data[field.name]"
class="size-3.5 shrink-0 cursor-pointer text-ink-gray-5 hover:text-ink-gray-8"
@click.stop="field.edit(data[field.name])"
/>
</div>
</div>
</div>
</FadedScrollableDiv>
@ -257,7 +262,7 @@ function evaluate(code, context = {}) {
:deep(.form-control button),
.dropdown-button {
border-color: transparent;
background: white;
background: transparent;
}
:deep(.form-control button) {

View File

@ -1,5 +1,5 @@
<template>
<div class="flex h-full flex-col gap-8 p-8">
<div class="flex h-full flex-col gap-8 p-8 text-ink-gray-9">
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
{{ __('Send Invites To') }}
</h2>
@ -18,7 +18,6 @@
type="select"
class="mt-4"
v-model="role"
variant="outline"
:label="__('Invite as')"
:options="[
{ label: __('Regular Access'), value: 'Sales User' },
@ -35,7 +34,7 @@
</div>
<ul class="flex flex-col gap-1">
<li
class="flex items-center justify-between px-2 py-1 rounded-lg bg-surface-menu-bar"
class="flex items-center justify-between px-2 py-1 rounded-lg bg-surface-gray-2"
v-for="user in pendingInvitations.data"
:key="user.name"
>

View File

@ -7,7 +7,7 @@
:label="profile.full_name"
/>
<div class="flex flex-col gap-1">
<span class="text-2xl font-semibold">{{ profile.full_name }}</span>
<span class="text-2xl font-semibold text-ink-gray-9">{{ profile.full_name }}</span>
<span class="text-base text-ink-gray-7">{{ profile.email }}</span>
</div>
</div>

View File

@ -6,8 +6,8 @@
>
<template #body>
<div class="flex h-[calc(100vh_-_8rem)]">
<div class="flex w-52 shrink-0 flex-col bg-surface-menu-bar p-2">
<h1 class="mb-3 px-2 pt-2 text-lg font-semibold">
<div class="flex w-52 shrink-0 flex-col bg-surface-gray-2 p-2">
<h1 class="mb-3 px-2 pt-2 text-lg font-semibold text-ink-gray-9">
{{ __('Settings') }}
</h1>
<div v-for="tab in tabs">
@ -25,15 +25,15 @@
class="w-full"
:class="
activeTab?.label == i.label
? 'bg-surface-white shadow-sm'
: 'hover:bg-surface-gray-2'
? 'bg-surface-selected shadow-sm hover:bg-surface-selected'
: 'hover:bg-surface-gray-3'
"
@click="activeTab = i"
/>
</nav>
</div>
</div>
<div class="flex flex-1 flex-col overflow-y-auto">
<div class="flex flex-1 flex-col overflow-y-auto bg-surface-modal">
<component :is="activeTab.component" v-if="activeTab" />
</div>
</div>
@ -41,7 +41,6 @@
</Dialog>
</template>
<script setup>
import ContactsIcon from '@/components/Icons/ContactsIcon.vue'
import WhatsAppIcon from '@/components/Icons/WhatsAppIcon.vue'
import ERPNextIcon from '@/components/Icons/ERPNextIcon.vue'
import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
@ -57,10 +56,12 @@ import {
showSettings,
activeSettingsPage,
} from '@/composables/settings'
import { Dialog } from 'frappe-ui'
import { ref, markRaw, computed, watch } from 'vue'
import { Dialog, Avatar } from 'frappe-ui'
import { ref, markRaw, computed, watch, h } from 'vue'
const { isManager } = usersStore()
const { isManager, getUser } = usersStore()
const user = computed(() => getUser() || {})
const tabs = computed(() => {
let _tabs = [
@ -70,7 +71,12 @@ const tabs = computed(() => {
items: [
{
label: __('Profile'),
icon: ContactsIcon,
icon: () =>
h(Avatar, {
size: 'xs',
label: user.value.full_name,
image: user.value.user_image,
}),
component: markRaw(ProfileSettings),
},
{

View File

@ -1,6 +1,6 @@
<template>
<div class="flex h-full flex-col gap-8">
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5 text-ink-gray-9">
<div>{{ title || __(doctype) }}</div>
<Badge
v-if="data.isDirty"

View File

@ -4,15 +4,15 @@
<template #item="{ element: section }">
<div class="flex flex-col gap-3">
<div
class="flex items-center justify-between rounded px-2.5 py-2 bg-surface-menu-bar"
class="flex items-center justify-between rounded px-2.5 py-2 bg-surface-gray-2"
>
<div
class="flex max-w-fit cursor-pointer items-center gap-2 text-base leading-4"
class="flex max-w-fit cursor-pointer items-center gap-2 text-base leading-4 text-ink-gray-9"
@click="section.opened = !section.opened"
>
<FeatherIcon
name="chevron-right"
class="h-4 text-ink-gray-9 transition-all duration-300 ease-in-out"
class="h-4 transition-all duration-300 ease-in-out"
:class="{ 'rotate-90': section.opened }"
/>
<div v-if="!section.editingLabel">
@ -62,7 +62,7 @@
>
<template #item="{ element: field }">
<div
class="px-2.5 py-2 border rounded text-base leading-4 text-ink-gray-8 flex items-center justify-between gap-2"
class="px-2.5 py-2 border border-outline-gray-modals rounded text-base leading-4 text-ink-gray-8 flex items-center justify-between gap-2"
>
<div class="flex items-center gap-2">
<DragVerticalIcon class="h-3.5 cursor-grab" />
@ -87,7 +87,7 @@
>
<template #target="{ togglePopover }">
<Button
class="w-full h-8 mt-1.5 !border-outline-gray-modals hover:!border-outline-gray-2"
class="w-full h-8 mt-1.5 !bg-surface-gray-1"
variant="outline"
@click="togglePopover()"
:label="__('Add Field')"
@ -98,7 +98,7 @@
</Button>
</template>
<template #item-label="{ option }">
<div class="flex flex-col gap-1">
<div class="flex flex-col gap-1 text-ink-gray-9">
<div>{{ option.label }}</div>
<div class="text-ink-gray-4 text-sm">
{{ `${option.fieldname} - ${option.fieldtype}` }}
@ -108,7 +108,7 @@
</Autocomplete>
<div
v-else
class="flex justify-center items-center border rounded border-dashed p-3"
class="flex justify-center items-center border rounded border-dashed border-outline-gray-modals p-3"
>
<div class="text-sm text-ink-gray-4">
{{ __('This section is not editable') }}

View File

@ -53,7 +53,7 @@
</div>
<div
v-else
class="flex flex-1 justify-center items-center text-ink-gray-5 bg-surface-menu-bar rounded border border-gray-50"
class="flex flex-1 justify-center items-center text-ink-gray-5 bg-surface-gray-2 rounded"
>
{{ __('Toggle on for preview') }}
</div>

View File

@ -1,7 +1,7 @@
<template>
<button
class="flex h-7 cursor-pointer items-center rounded text-ink-gray-7 duration-300 ease-in-out focus:outline-none focus:transition-none focus-visible:rounded focus-visible:ring-2 focus-visible:ring-outline-gray-3"
:class="isActive ? 'bg-surface-white shadow-sm' : 'hover:bg-surface-gray-2'"
:class="isActive ? 'bg-surface-selected shadow-sm' : 'hover:bg-surface-gray-2'"
@click="handleClick"
>
<div
@ -55,7 +55,7 @@ const route = useRoute()
const props = defineProps({
icon: {
type: [Object, String],
type: [Object, String, Function],
},
label: {
type: String,

View File

@ -26,7 +26,7 @@
<template v-if="!hideLabel" #prefix><SortIcon class="h-4" /></template>
<template v-if="sortValues?.size" #suffix>
<div
class="flex h-5 w-5 items-center justify-center rounded bg-surface-gray-7 pt-[1px] text-2xs font-medium text-ink-white"
class="flex h-5 w-5 items-center justify-center rounded-[5px] bg-surface-white pt-px text-xs font-medium text-ink-gray-8 shadow-sm"
>
{{ sortValues.size }}
</div>
@ -52,6 +52,7 @@
</Button>
<Button
:label="getSortLabel()"
class="shrink-0"
:class="sortValues.size ? 'rounded-l-none' : ''"
>
<template v-if="!hideLabel && !sortValues?.size" #prefix>
@ -67,7 +68,9 @@
</div>
</template>
<template #body="{ close }">
<div class="my-2 rounded-lg border border-gray-100 bg-surface-white shadow-xl">
<div
class="my-2 min-w-40 rounded-lg bg-surface-modal shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div class="min-w-60 p-2">
<div
v-if="sortValues?.size"
@ -82,7 +85,7 @@
<div class="handle flex h-7 w-7 items-center justify-center">
<DragIcon class="h-4 w-4 cursor-grab text-ink-gray-5" />
</div>
<div class="flex">
<div class="flex flex-1 [&>_div]:w-full">
<Button
size="md"
class="rounded-r-none border-r"
@ -97,7 +100,6 @@
<DesendingIcon v-else class="h-4" />
</Button>
<Autocomplete
class="!w-32"
:value="sort.fieldname"
:options="sortOptions.data"
@change="(e) => updateSort(e, i)"
@ -240,7 +242,7 @@ function getSortLabel() {
if (!sortValues.value.size) return __('Sort')
let values = Array.from(sortValues.value)
let label = sortOptions.data?.find(
(option) => option.value === values[0].fieldname
(option) => option.value === values[0].fieldname,
)?.label
return label || sort.fieldname

View File

@ -27,10 +27,8 @@
</template>
<template #item="{ item, active }">
<button
:class="[
active ? 'bg-surface-gray-2' : 'text-ink-gray-8',
'group flex gap-4 h-7 w-full justify-between items-center rounded px-2 text-base',
]"
class="group flex text-ink-gray-6 gap-4 h-7 w-full justify-between items-center rounded px-2 text-base"
:class="{ 'bg-surface-gray-3': active }"
@click="item.onClick"
>
<div class="flex items-center">

View File

@ -14,7 +14,7 @@
>
<div class="w-full">
<button
class="flex w-full items-center justify-between focus:outline-none"
class="flex h-7 w-full items-center justify-between gap-2 rounded bg-surface-gray-2 px-2 py-1 transition-colors hover:bg-surface-gray-3 border border-transparent focus:border-outline-gray-4 focus:outline-none focus:ring-2 focus:ring-outline-gray-3"
:class="inputClasses"
@click="() => togglePopover()"
>
@ -41,11 +41,13 @@
</template>
<template #body="{ isOpen }">
<div v-show="isOpen">
<div class="mt-1 rounded-lg bg-surface-white py-1 text-base shadow-2xl">
<div class="relative px-1.5 pt-0.5">
<div
class="relative mt-1 rounded-lg bg-surface-modal text-base shadow-2xl"
>
<div class="relative px-1.5 pt-1.5">
<ComboboxInput
ref="search"
class="form-input w-full"
class="form-input w-full focus:bg-surface-gray-3 hover:bg-surface-gray-4 text-ink-gray-8"
type="text"
@change="
(e) => {
@ -60,7 +62,7 @@
class="absolute right-1.5 inline-flex h-7 w-7 items-center justify-center"
@click="selectedValue = null"
>
<FeatherIcon name="x" class="w-4" />
<FeatherIcon name="x" class="w-4 text-ink-gray-8" />
</button>
</div>
<ComboboxOptions
@ -75,7 +77,7 @@
>
<div
v-if="group.group && !group.hideLabel"
class="px-2.5 py-1.5 text-sm font-medium text-ink-gray-4"
class="truncate bg-surface-modal px-2.5 py-1.5 text-sm font-medium text-ink-gray-5"
>
{{ group.group }}
</div>
@ -88,8 +90,8 @@
>
<li
:class="[
'flex items-center rounded px-2.5 py-1.5 text-base',
{ 'bg-surface-gray-2': active },
'flex cursor-pointer items-center rounded px-2.5 py-1.5 text-base',
{ 'bg-surface-gray-3': active },
]"
>
<slot
@ -100,19 +102,24 @@
name="item-label"
v-bind="{ active, selected, option }"
>
{{ option.label }}
<div class="flex-1 truncate text-ink-gray-7">
{{ option.label }}
</div>
</slot>
</li>
</ComboboxOption>
</div>
<li
v-if="groups.length == 0"
class="mt-1.5 rounded-md px-2.5 py-1.5 text-base text-ink-gray-5"
class="my-1.5 rounded-md px-2.5 py-1.5 text-base text-ink-gray-5"
>
No results found
</li>
</ComboboxOptions>
<div v-if="slots.footer" class="border-t p-1.5 pb-0.5">
<div
v-if="slots.footer"
class="border-t border-outline-gray-modals p-1.5"
>
<slot
name="footer"
v-bind="{ value: search?.el._value, close }"
@ -219,7 +226,7 @@ function filterOptions(options) {
return options.filter((option) => {
let searchTexts = [option.label, option.value]
return searchTexts.some((text) =>
(text || '').toString().toLowerCase().includes(query.value.toLowerCase())
(text || '').toString().toLowerCase().includes(query.value.toLowerCase()),
)
})
}
@ -272,7 +279,9 @@ const inputClasses = computed(() => {
'border border-outline-gray-2 bg-surface-white placeholder-ink-gray-4 hover:border-outline-gray-3 hover:shadow-sm focus:bg-surface-white focus:border-outline-gray-4 focus:shadow-sm focus:ring-0 focus-visible:ring-2 focus-visible:ring-outline-gray-3',
disabled: [
'border bg-surface-menu-bar placeholder-ink-gray-3',
props.variant === 'outline' ? 'border-outline-gray-2' : 'border-transparent',
props.variant === 'outline'
? 'border-outline-gray-2'
: 'border-transparent',
],
}[variant]

View File

@ -16,14 +16,14 @@
<template #body>
<div
class="rounded-lg bg-surface-white shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
class="mt-2 min-w-40 divide-y divide-outline-gray-modals rounded-lg bg-surface-modal shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none"
:class="{
'mt-2': ['bottom', 'left', 'right'].includes(placement),
'ml-2': placement == 'right-start',
}"
>
<MenuItems
class="min-w-40 divide-y divide-gray-100"
class="min-w-40 divide-y divide-outline-gray-modals"
:class="{
'left-0 origin-top-left': placement == 'left',
'right-0 origin-top-right': placement == 'right',
@ -52,7 +52,7 @@
<button
v-else
:class="[
active ? 'bg-surface-gray-2' : 'text-ink-gray-8',
active ? 'bg-surface-gray-3' : 'text-ink-gray-6',
'group flex h-7 w-full items-center rounded px-2 text-base',
]"
@click="item.onClick"
@ -68,7 +68,7 @@
v-else-if="item.icon"
:is="item.icon"
/>
<span class="whitespace-nowrap">
<span class="whitespace-nowrap text-ink-gray-7">
{{ item.label }}
</span>
</button>

View File

@ -60,11 +60,13 @@
clip-path: inset(22px 0 0 0);
"
>
<CameraIcon class="h-6 w-6 cursor-pointer text-ink-white" />
<CameraIcon
class="h-6 w-6 cursor-pointer text-white"
/>
</div>
</component>
</div>
<div class="flex flex-col gap-2 truncate">
<div class="flex flex-col gap-2 truncate text-ink-gray-9">
<div class="truncate text-2xl font-medium">
<span v-if="contact.data.salutation">
{{ contact.data.salutation + '. ' }}
@ -150,7 +152,7 @@
</div>
</div>
</Resizer>
<Tabs class="overflow-hidden" v-model="tabIndex" :tabs="tabs">
<Tabs class="!h-full" v-model="tabIndex" :tabs="tabs">
<template #tab="{ tab, selected }">
<button
class="group flex items-center gap-2 border-b border-transparent py-2.5 text-base text-ink-gray-5 duration-300 ease-in-out hover:border-outline-gray-3 hover:text-ink-gray-9"
@ -669,4 +671,4 @@ const dealColumns = [
width: '8rem',
},
]
</script>
</script>

View File

@ -48,7 +48,7 @@
</Tabs>
<Resizer side="right" class="flex flex-col justify-between border-l">
<div
class="flex h-10.5 cursor-copy items-center border-b px-5 py-2.5 text-lg font-medium"
class="flex h-10.5 cursor-copy items-center border-b px-5 py-2.5 text-lg font-medium text-ink-gray-9"
@click="copyToClipboard(deal.data.name)"
>
{{ __(deal.data.name) }}
@ -64,7 +64,7 @@
/>
</div>
</Tooltip>
<div class="flex flex-col gap-2.5 truncate">
<div class="flex flex-col gap-2.5 truncate text-ink-gray-9">
<Tooltip :text="organization.data?.name || __('Set an organization')">
<div class="truncate text-2xl font-medium">
{{ organization.data?.name || __('Untitled') }}

View File

@ -53,7 +53,7 @@
</Tabs>
<Resizer class="flex flex-col justify-between border-l" side="right">
<div
class="flex h-10.5 cursor-copy items-center border-b px-5 py-2.5 text-lg font-medium"
class="flex h-10.5 cursor-copy items-center border-b px-5 py-2.5 text-lg font-medium text-ink-gray-9"
@click="copyToClipboard(lead.data.name)"
>
{{ __(lead.data.name) }}
@ -102,13 +102,13 @@
clip-path: inset(12px 0 0 0);
"
>
<CameraIcon class="size-4 cursor-pointer text-ink-white" />
<CameraIcon class="size-4 cursor-pointer text-white" />
</div>
</component>
</div>
<div class="flex flex-col gap-2.5 truncate">
<Tooltip :text="lead.data.lead_name || __('Set first name')">
<div class="truncate text-2xl font-medium">
<div class="truncate text-2xl font-medium text-ink-gray-9">
{{ lead.data.lead_name || __('Untitled') }}
</div>
</Tooltip>

View File

@ -53,12 +53,12 @@
clip-path: inset(22px 0 0 0);
"
>
<CameraIcon class="h-6 w-6 cursor-pointer text-ink-white" />
<CameraIcon class="h-6 w-6 cursor-pointer text-white" />
</div>
</component>
</div>
<div class="flex flex-col gap-2 truncate">
<div class="truncate text-lg font-medium">
<div class="truncate text-lg font-medium text-ink-gray-9">
<span v-if="contact.data.salutation">
{{ contact.data.salutation + '. ' }}
</span>

View File

@ -22,10 +22,10 @@
</Tooltip>
</template>
</LayoutHeader>
<div class="flex flex-col overflow-hidden">
<div class="flex flex-col overflow-hidden text-ink-gray-9">
<div
v-if="notifications.data?.length"
class="divide-y overflow-y-auto text-base"
class="divide-y divide-outline-gray-1 overflow-y-auto text-base"
>
<RouterLink
v-for="n in notifications.data"

View File

@ -56,12 +56,12 @@
clip-path: inset(22px 0 0 0);
"
>
<CameraIcon class="h-6 w-6 cursor-pointer text-ink-white" />
<CameraIcon class="h-6 w-6 cursor-pointer text-white" />
</div>
</component>
</div>
<div class="flex flex-col gap-2 truncate">
<div class="truncate text-lg font-medium">
<div class="truncate text-lg font-medium text-ink-gray-9">
{{ organization.doc.name }}
</div>
<div class="flex items-center gap-1.5">

View File

@ -31,7 +31,7 @@
@click="editNote(note)"
>
<div class="flex items-center justify-between">
<div class="truncate text-lg font-medium">
<div class="truncate text-lg font-medium text-ink-gray-9">
{{ note.title }}
</div>
<Dropdown

View File

@ -60,12 +60,12 @@
clip-path: inset(22px 0 0 0);
"
>
<CameraIcon class="h-6 w-6 cursor-pointer text-ink-white" />
<CameraIcon class="h-6 w-6 cursor-pointer text-white" />
</div>
</component>
</div>
<div class="flex flex-col gap-2 truncate">
<div class="truncate text-2xl font-medium">
<div class="truncate text-2xl font-medium text-ink-gray-9">
<span>{{ organization.doc.name }}</span>
</div>
<div
@ -135,7 +135,7 @@
</div>
</div>
</Resizer>
<Tabs class="overflow-hidden" v-model="tabIndex" :tabs="tabs">
<Tabs class="!h-full" v-model="tabIndex" :tabs="tabs">
<template #tab="{ tab, selected }">
<button
class="group flex items-center gap-2 border-b border-transparent py-2.5 text-base text-ink-gray-5 duration-300 ease-in-out hover:border-outline-gray-3 hover:text-ink-gray-9"