-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #42 from krantheman/feat-settings
feat: add Settings
- Loading branch information
Showing
8 changed files
with
350 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<template> | ||
<label class="block pt-2 text-sm"> | ||
<span class="mb-2 block leading-4 text-gray-700">{{ props.label }}</span> | ||
<button | ||
class="border-2 rounded-lg bg-gray-100 p-2 w-full flex items-center" | ||
@click="copyToClipBoard(props.value)" | ||
> | ||
<span class="text-gray-800">{{ props.value }}</span> | ||
<span class="border rounded bg-white p-1 text-gray-600 text-xs ml-auto"> | ||
{{ message }} | ||
</span> | ||
</button> | ||
</label> | ||
</template> | ||
<script setup> | ||
import { ref } from 'vue' | ||
const message = ref('Copy') | ||
const props = defineProps({ | ||
label: { | ||
type: String, | ||
required: true, | ||
}, | ||
value: { | ||
type: String, | ||
required: true, | ||
}, | ||
}) | ||
const copyToClipBoard = async (text) => { | ||
await navigator.clipboard.writeText(text) | ||
message.value = 'Copied!' | ||
setTimeout(() => { | ||
message.value = 'Copy' | ||
}, 2000) | ||
} | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<template> | ||
<Dialog v-model="show" :options="{ title: __('Settings'), size: '5xl' }"> | ||
<template #body> | ||
<div class="flex" :style="{ height: 'calc(100vh - 9rem)' }"> | ||
<div class="flex w-52 shrink-0 flex-col bg-gray-50 py-3 p-4 border-r"> | ||
<h1 class="text-xl font-semibold leading-6 text-gray-900 px-2">Settings</h1> | ||
<div class="mt-3 space-y-1"> | ||
<button | ||
v-for="tab in tabs" | ||
:key="tab.label" | ||
class="flex h-7 w-full items-center gap-2 rounded px-2 py-1" | ||
:class="[ | ||
activeTab.label == tab.label ? 'bg-gray-200' : 'hover:bg-gray-100', | ||
]" | ||
@click="activeTab = tab" | ||
> | ||
<component :is="tab.icon" class="h-4 w-4 text-gray-700 stroke-[1.5]" /> | ||
<span class="text-base text-gray-800"> | ||
{{ tab.label }} | ||
</span> | ||
</button> | ||
</div> | ||
</div> | ||
<div class="flex flex-1 flex-col p-12 overflow-y-auto"> | ||
<component :is="activeTab.component" v-if="activeTab" /> | ||
</div> | ||
<Button | ||
class="my-3 mr-4 absolute right-0" | ||
variant="ghost" | ||
icon="x" | ||
@click="show = false" | ||
/> | ||
</div> | ||
</template> | ||
</Dialog> | ||
</template> | ||
<script setup> | ||
import { markRaw, ref } from 'vue' | ||
import UserSettings from '@/components/Settings/UserSettings.vue' | ||
import MailboxSettings from '@/components/Settings/MailboxSettings.vue' | ||
import { Dialog, Button } from 'frappe-ui' | ||
import { User, Mailbox } from 'lucide-vue-next' | ||
const show = defineModel() | ||
const tabs = [ | ||
{ | ||
label: 'User', | ||
icon: User, | ||
component: markRaw(UserSettings), | ||
}, | ||
{ | ||
label: 'Mailbox', | ||
icon: Mailbox, | ||
component: markRaw(MailboxSettings), | ||
}, | ||
] | ||
const activeTab = ref(tabs[0]) | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
<template> | ||
<h1 class="font-semibold mb-8">Mailbox</h1> | ||
<div class="flex items-center mb-3"> | ||
<span class="font-medium leading-normal text-gray-800 text-base">Email Address</span> | ||
<Link | ||
v-model="email" | ||
doctype="Mailbox" | ||
:filters="{ user: userResource.data?.name }" | ||
class="ml-auto" | ||
/> | ||
</div> | ||
<div v-if="mailbox.doc" class="space-y-1.5"> | ||
<Switch | ||
label="Enabled" | ||
v-model="mailbox.doc.enabled" | ||
@update:modelValue="mailbox.setValue.submit({ enabled: mailbox.doc.enabled })" | ||
/> | ||
<Switch | ||
label="Incoming" | ||
v-model="mailbox.doc.incoming" | ||
@update:modelValue="mailbox.setValue.submit({ incoming: mailbox.doc.incoming })" | ||
/> | ||
<Switch | ||
label="Outgoing" | ||
v-model="mailbox.doc.outgoing" | ||
@update:modelValue="mailbox.setValue.submit({ outgoing: mailbox.doc.outgoing })" | ||
/> | ||
<Switch | ||
label="Default Outgoing" | ||
v-model="mailbox.doc.is_default" | ||
:disabled="!mailbox.doc.outgoing" | ||
@update:modelValue="mailbox.setValue.submit({ is_default: mailbox.doc.is_default })" | ||
/> | ||
<Switch | ||
label="Track Outgoing Mail" | ||
v-model="mailbox.doc.track_outgoing_mail" | ||
:disabled="!mailbox.doc.outgoing" | ||
@update:modelValue=" | ||
mailbox.setValue.submit({ track_outgoing_mail: mailbox.doc.track_outgoing_mail }) | ||
" | ||
/> | ||
<Switch | ||
label="Create Mail Contact" | ||
v-model="mailbox.doc.create_mail_contact" | ||
@update:modelValue=" | ||
mailbox.setValue.submit({ create_mail_contact: mailbox.doc.create_mail_contact }) | ||
" | ||
/> | ||
<div class="mx-2.5 space-y-2.5 pt-0.5"> | ||
<div class="flex items-center justify-between"> | ||
<span class="font-medium leading-normal text-gray-800 text-base"> | ||
Display Name | ||
</span> | ||
<TextInput | ||
v-model="mailbox.doc.display_name" | ||
@input=" | ||
mailbox.setValueDebounced.submit({ | ||
display_name: mailbox.doc.display_name, | ||
}) | ||
" | ||
/> | ||
</div> | ||
<div class="flex items-center justify-between"> | ||
<span class="font-medium leading-normal text-gray-800 text-base">Reply To</span> | ||
<TextInput | ||
v-model="mailbox.doc.reply_to" | ||
@input="mailbox.setValueDebounced.submit({ reply_to: mailbox.doc.reply_to })" | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
<script setup> | ||
import { ref, watch, onMounted } from 'vue' | ||
import { Switch, TextInput, createDocumentResource } from 'frappe-ui' | ||
import Link from '@/components/Controls/Link.vue' | ||
import { userStore } from '@/stores/user' | ||
const { userResource, defaultOutgoing } = userStore() | ||
const email = ref(defaultOutgoing.data) | ||
const fetchMailbox = () => { | ||
mailbox.name = email.value | ||
mailbox.reload() | ||
} | ||
onMounted(fetchMailbox) | ||
watch(email, fetchMailbox) | ||
const mailbox = createDocumentResource({ | ||
doctype: 'Mailbox', | ||
name: email.value, | ||
auto: false, | ||
transform(data) { | ||
for (const d of [ | ||
'enabled', | ||
'incoming', | ||
'outgoing', | ||
'is_default', | ||
'track_outgoing_mail', | ||
'create_mail_contact', | ||
]) { | ||
data[d] = !!data[d] | ||
} | ||
}, | ||
}) | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<template> | ||
<h1 class="font-semibold mb-8">User</h1> | ||
<div class="flex justify-start w-full items-center gap-x-4"> | ||
<Avatar | ||
:image="user.data?.user_image" | ||
:label="user.data?.full_name" | ||
size="3xl" | ||
class="w-20 h-20" | ||
/> | ||
<div class="flex flex-col"> | ||
<span class="text-xl font-semibold">{{ user.data?.full_name }}</span> | ||
<span class="text-base text-gray-700">{{ user.data?.email }}</span> | ||
</div> | ||
</div> | ||
|
||
<div class="mt-12 mb-4 flex items-center"> | ||
<h1 class="font-semibold">API Access</h1> | ||
<Button | ||
:label="user.data?.api_key ? 'Regenerate Secret' : 'Generate Keys'" | ||
class="ml-auto" | ||
@click="generateKeys.submit()" | ||
/> | ||
</div> | ||
|
||
<Copy v-if="user.data?.api_key" label="API Key" :value="user.data?.api_key" /> | ||
|
||
<div v-else class="mt-2"> | ||
<p class="text-base">You don't have an API key yet. Generate one to access the API.</p> | ||
</div> | ||
|
||
<Dialog v-model="showSecret" :options="{ title: __('API Access') }"> | ||
<template #body-content> | ||
<p class="text-base"> | ||
Please copy the API secret now. You won’t be able to see it again! | ||
</p> | ||
<Copy label="API Key" :value="user.data?.api_key" /> | ||
<Copy label="API Secret" :value="apiSecret" /> | ||
</template> | ||
</Dialog> | ||
</template> | ||
<script setup> | ||
import { ref, inject } from 'vue' | ||
import Copy from '@/components/Controls/Copy.vue' | ||
import { Avatar, Button, Dialog, createResource } from 'frappe-ui' | ||
const user = inject('$user') | ||
const showSecret = ref(false) | ||
const apiSecret = ref('') | ||
const generateKeys = createResource({ | ||
url: 'frappe.core.doctype.user.user.generate_keys', | ||
makeParams() { | ||
return { | ||
user: user.data?.name, | ||
} | ||
}, | ||
onSuccess(data) { | ||
if (!user.data?.api_key) user.reload() | ||
apiSecret.value = data.api_secret | ||
showSecret.value = true | ||
}, | ||
}) | ||
</script> |
Oops, something went wrong.