refactor: general settings
This commit is contained in:
parent
a5d3694386
commit
c7fbd6f8f1
5
frontend/components.d.ts
vendored
5
frontend/components.d.ts
vendored
@ -31,6 +31,7 @@ declare module 'vue' {
|
|||||||
Autocomplete: typeof import('./src/components/frappe-ui/Autocomplete.vue')['default']
|
Autocomplete: typeof import('./src/components/frappe-ui/Autocomplete.vue')['default']
|
||||||
AvatarIcon: typeof import('./src/components/Icons/AvatarIcon.vue')['default']
|
AvatarIcon: typeof import('./src/components/Icons/AvatarIcon.vue')['default']
|
||||||
BrandLogo: typeof import('./src/components/BrandLogo.vue')['default']
|
BrandLogo: typeof import('./src/components/BrandLogo.vue')['default']
|
||||||
|
BrandSettings: typeof import('./src/components/Settings/General/BrandSettings.vue')['default']
|
||||||
BulkDeleteLinkedDocModal: typeof import('./src/components/BulkDeleteLinkedDocModal.vue')['default']
|
BulkDeleteLinkedDocModal: typeof import('./src/components/BulkDeleteLinkedDocModal.vue')['default']
|
||||||
CalendarIcon: typeof import('./src/components/Icons/CalendarIcon.vue')['default']
|
CalendarIcon: typeof import('./src/components/Icons/CalendarIcon.vue')['default']
|
||||||
CallArea: typeof import('./src/components/Activities/CallArea.vue')['default']
|
CallArea: typeof import('./src/components/Activities/CallArea.vue')['default']
|
||||||
@ -127,7 +128,8 @@ declare module 'vue' {
|
|||||||
FormattedInput: typeof import('./src/components/Controls/FormattedInput.vue')['default']
|
FormattedInput: typeof import('./src/components/Controls/FormattedInput.vue')['default']
|
||||||
FrappeCloudIcon: typeof import('./src/components/Icons/FrappeCloudIcon.vue')['default']
|
FrappeCloudIcon: typeof import('./src/components/Icons/FrappeCloudIcon.vue')['default']
|
||||||
GenderIcon: typeof import('./src/components/Icons/GenderIcon.vue')['default']
|
GenderIcon: typeof import('./src/components/Icons/GenderIcon.vue')['default']
|
||||||
GeneralSettings: typeof import('./src/components/Settings/GeneralSettings.vue')['default']
|
GeneralSettings: typeof import('./src/components/Settings/General/GeneralSettings.vue')['default']
|
||||||
|
GeneralSettingsPage: typeof import('./src/components/Settings/General/GeneralSettingsPage.vue')['default']
|
||||||
GlobalModals: typeof import('./src/components/Modals/GlobalModals.vue')['default']
|
GlobalModals: typeof import('./src/components/Modals/GlobalModals.vue')['default']
|
||||||
GoogleIcon: typeof import('./src/components/Icons/GoogleIcon.vue')['default']
|
GoogleIcon: typeof import('./src/components/Icons/GoogleIcon.vue')['default']
|
||||||
Grid: typeof import('./src/components/Controls/Grid.vue')['default']
|
Grid: typeof import('./src/components/Controls/Grid.vue')['default']
|
||||||
@ -138,6 +140,7 @@ declare module 'vue' {
|
|||||||
GroupByIcon: typeof import('./src/components/Icons/GroupByIcon.vue')['default']
|
GroupByIcon: typeof import('./src/components/Icons/GroupByIcon.vue')['default']
|
||||||
HeartIcon: typeof import('./src/components/Icons/HeartIcon.vue')['default']
|
HeartIcon: typeof import('./src/components/Icons/HeartIcon.vue')['default']
|
||||||
HelpIcon: typeof import('./src/components/Icons/HelpIcon.vue')['default']
|
HelpIcon: typeof import('./src/components/Icons/HelpIcon.vue')['default']
|
||||||
|
HomeActions: typeof import('./src/components/Settings/General/HomeActions.vue')['default']
|
||||||
Icon: typeof import('./src/components/Icon.vue')['default']
|
Icon: typeof import('./src/components/Icon.vue')['default']
|
||||||
IconPicker: typeof import('./src/components/IconPicker.vue')['default']
|
IconPicker: typeof import('./src/components/IconPicker.vue')['default']
|
||||||
ImageUploader: typeof import('./src/components/Controls/ImageUploader.vue')['default']
|
ImageUploader: typeof import('./src/components/Controls/ImageUploader.vue')['default']
|
||||||
|
|||||||
@ -1,31 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex h-full flex-col gap-6 p-8 text-ink-gray-8">
|
<div class="flex h-full flex-col gap-6 px-6 py-8 text-ink-gray-8">
|
||||||
<div class="flex justify-between">
|
<!-- Header -->
|
||||||
<div class="flex flex-col gap-1 w-9/12">
|
<div class="flex px-2 justify-between">
|
||||||
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
<div class="flex items-center gap-1 -ml-4 w-9/12">
|
||||||
{{ __('General') }}
|
<Button
|
||||||
<Badge
|
variant="ghost"
|
||||||
v-if="settings.isDirty"
|
icon-left="chevron-left"
|
||||||
:label="__('Not Saved')"
|
:label="__('Brand settings')"
|
||||||
variant="subtle"
|
size="md"
|
||||||
theme="orange"
|
@click="() => emit('updateStep', 'general-settings')"
|
||||||
/>
|
class="text-xl !h-7 font-semibold hover:bg-transparent focus:bg-transparent focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:none active:bg-transparent active:outline-none active:ring-0 active:ring-offset-0 active:text-ink-gray-5"
|
||||||
</h2>
|
/>
|
||||||
<p class="text-p-base text-ink-gray-6">
|
<Badge
|
||||||
{{ __('Configure general settings for your CRM') }}
|
v-if="settings.isDirty"
|
||||||
</p>
|
:label="__('Not Saved')"
|
||||||
|
variant="subtle"
|
||||||
|
theme="orange"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex item-center space-x-2 w-3/12 justify-end">
|
<div class="flex item-center space-x-2 w-3/12 justify-end">
|
||||||
<Button
|
<Button
|
||||||
variant="solid"
|
|
||||||
:label="__('Update')"
|
:label="__('Update')"
|
||||||
|
icon-left="plus"
|
||||||
|
variant="solid"
|
||||||
:disabled="!settings.isDirty"
|
:disabled="!settings.isDirty"
|
||||||
|
:loading="settings.loading"
|
||||||
@click="updateSettings"
|
@click="updateSettings"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="settings.doc" class="flex-1 flex flex-col gap-8 overflow-y-auto">
|
<!-- Fields -->
|
||||||
|
<div class="flex flex-1 flex-col p-2 gap-4 overflow-y-auto">
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
<FormControl
|
<FormControl
|
||||||
type="text"
|
type="text"
|
||||||
@ -36,7 +42,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- logo -->
|
<!-- logo -->
|
||||||
|
|
||||||
<div class="flex flex-col justify-between gap-4">
|
<div class="flex flex-col justify-between gap-4">
|
||||||
<span class="text-base font-semibold text-ink-gray-8">
|
<span class="text-base font-semibold text-ink-gray-8">
|
||||||
{{ __('Logo') }}
|
{{ __('Logo') }}
|
||||||
@ -71,7 +76,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- favicon -->
|
<!-- favicon -->
|
||||||
|
|
||||||
<div class="flex flex-col justify-between gap-4">
|
<div class="flex flex-col justify-between gap-4">
|
||||||
<span class="text-base font-semibold text-ink-gray-8">
|
<span class="text-base font-semibold text-ink-gray-8">
|
||||||
{{ __('Favicon') }}
|
{{ __('Favicon') }}
|
||||||
@ -104,33 +108,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Home actions -->
|
|
||||||
|
|
||||||
<div class="flex flex-col justify-between gap-4">
|
|
||||||
<span class="text-base font-semibold text-ink-gray-8">
|
|
||||||
{{ __('Home actions') }}
|
|
||||||
</span>
|
|
||||||
<div class="flex flex-1">
|
|
||||||
<Grid
|
|
||||||
v-model="settings.doc.dropdown_items"
|
|
||||||
doctype="CRM Dropdown Item"
|
|
||||||
parentDoctype="FCRM Settings"
|
|
||||||
parentFieldname="dropdown_items"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="errorMessage">
|
||||||
<ErrorMessage :message="settings.save.error" />
|
<ErrorMessage :message="__(errorMessage)" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import ImageUploader from '@/components/Controls/ImageUploader.vue'
|
import ImageUploader from '@/components/Controls/ImageUploader.vue'
|
||||||
import Grid from '@/components/Controls/Grid.vue'
|
import { FormControl, ErrorMessage } from 'frappe-ui'
|
||||||
import { FormControl, Badge, ErrorMessage } from 'frappe-ui'
|
|
||||||
import { getSettings } from '@/stores/settings'
|
import { getSettings } from '@/stores/settings'
|
||||||
import { showSettings } from '@/composables/settings'
|
import { showSettings } from '@/composables/settings'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
const { _settings: settings, setupBrand } = getSettings()
|
const { _settings: settings, setupBrand } = getSettings()
|
||||||
|
|
||||||
@ -142,4 +131,7 @@ function updateSettings() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['updateStep'])
|
||||||
|
const errorMessage = ref('')
|
||||||
</script>
|
</script>
|
||||||
54
frontend/src/components/Settings/General/GeneralSettings.vue
Normal file
54
frontend/src/components/Settings/General/GeneralSettings.vue
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex h-full flex-col gap-6 p-8 text-ink-gray-8">
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
<h2 class="flex gap-2 text-xl font-semibold leading-none h-5">
|
||||||
|
{{ __('General') }}
|
||||||
|
</h2>
|
||||||
|
<p class="text-p-base text-ink-gray-6">
|
||||||
|
{{ __('Configure general settings for your CRM') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-1 flex flex-col overflow-y-auto">
|
||||||
|
<template v-for="(setting, i) in settings" :key="setting.name">
|
||||||
|
<li
|
||||||
|
class="flex items-center justify-between p-3 cursor-pointer hover:bg-surface-menu-bar rounded"
|
||||||
|
@click="() => emit('updateStep', setting.name)"
|
||||||
|
>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="text-base font-medium text-ink-gray-7 truncate">
|
||||||
|
{{ __(setting.label) }}
|
||||||
|
</div>
|
||||||
|
<div class="text-p-base text-ink-gray-5 truncate">
|
||||||
|
{{ __(setting.description) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<FeatherIcon name="chevron-right" class="text-ink-gray-7 size-4" />
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<div
|
||||||
|
v-if="settings !== i + 1"
|
||||||
|
class="h-px border-t mx-2 border-outline-gray-modals"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const emit = defineEmits(['updateStep'])
|
||||||
|
|
||||||
|
const settings = [
|
||||||
|
{
|
||||||
|
name: 'brand-settings',
|
||||||
|
label: 'Brand settings',
|
||||||
|
description: 'Configure your brand name, logo and favicon',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'home-actions',
|
||||||
|
label: 'Home actions',
|
||||||
|
description: 'Configure actions that appear on the home dropdown',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
</script>
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<component :is="getComponent(step)" :data="data" @updateStep="updateStep" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import GeneralSettings from './GeneralSettings.vue'
|
||||||
|
import BrandSettings from './BrandSettings.vue'
|
||||||
|
import HomeActions from './HomeActions.vue'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const step = ref('general-settings')
|
||||||
|
const data = ref(null)
|
||||||
|
|
||||||
|
function updateStep(newStep, _data) {
|
||||||
|
step.value = newStep
|
||||||
|
data.value = _data
|
||||||
|
}
|
||||||
|
|
||||||
|
function getComponent(step) {
|
||||||
|
switch (step) {
|
||||||
|
case 'general-settings':
|
||||||
|
return GeneralSettings
|
||||||
|
case 'brand-settings':
|
||||||
|
return BrandSettings
|
||||||
|
case 'home-actions':
|
||||||
|
return HomeActions
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
60
frontend/src/components/Settings/General/HomeActions.vue
Normal file
60
frontend/src/components/Settings/General/HomeActions.vue
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex h-full flex-col gap-6 p-8 text-ink-gray-8">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<div class="flex gap-1 -ml-4 w-9/12">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
icon-left="chevron-left"
|
||||||
|
:label="__('Home actions')"
|
||||||
|
size="md"
|
||||||
|
@click="() => emit('updateStep', 'general-settings')"
|
||||||
|
class="text-xl !h-7 font-semibold hover:bg-transparent focus:bg-transparent focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:none active:bg-transparent active:outline-none active:ring-0 active:ring-offset-0 active:text-ink-gray-5"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex item-center space-x-2 w-3/12 justify-end">
|
||||||
|
<Button
|
||||||
|
:label="__('Update')"
|
||||||
|
icon-left="plus"
|
||||||
|
variant="solid"
|
||||||
|
:disabled="!settings.isDirty"
|
||||||
|
:loading="settings.loading"
|
||||||
|
@click="updateSettings"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Fields -->
|
||||||
|
<div class="flex flex-1 flex-col gap-4 overflow-y-auto">
|
||||||
|
<Grid
|
||||||
|
v-model="settings.doc.dropdown_items"
|
||||||
|
doctype="CRM Dropdown Item"
|
||||||
|
parentDoctype="FCRM Settings"
|
||||||
|
parentFieldname="dropdown_items"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="errorMessage">
|
||||||
|
<ErrorMessage :message="__(errorMessage)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import Grid from '@/components/Controls/Grid.vue'
|
||||||
|
import { ErrorMessage } from 'frappe-ui'
|
||||||
|
import { getSettings } from '@/stores/settings'
|
||||||
|
import { showSettings } from '@/composables/settings'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const { _settings: settings } = getSettings()
|
||||||
|
|
||||||
|
const emit = defineEmits(['updateStep'])
|
||||||
|
const errorMessage = ref('')
|
||||||
|
|
||||||
|
function updateSettings() {
|
||||||
|
settings.save.submit(null, {
|
||||||
|
onSuccess: () => {
|
||||||
|
showSettings.value = false
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -47,7 +47,7 @@ import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
|
|||||||
import Email2Icon from '@/components/Icons/Email2Icon.vue'
|
import Email2Icon from '@/components/Icons/Email2Icon.vue'
|
||||||
import EmailTemplateIcon from '@/components/Icons/EmailTemplateIcon.vue'
|
import EmailTemplateIcon from '@/components/Icons/EmailTemplateIcon.vue'
|
||||||
import Users from '@/components/Settings/Users.vue'
|
import Users from '@/components/Settings/Users.vue'
|
||||||
import GeneralSettings from '@/components/Settings/GeneralSettings.vue'
|
import GeneralSettingsPage from '@/components/Settings/General/GeneralSettingsPage.vue'
|
||||||
import InviteUserPage from '@/components/Settings/InviteUserPage.vue'
|
import InviteUserPage from '@/components/Settings/InviteUserPage.vue'
|
||||||
import ProfileSettings from '@/components/Settings/ProfileSettings.vue'
|
import ProfileSettings from '@/components/Settings/ProfileSettings.vue'
|
||||||
import WhatsAppSettings from '@/components/Settings/WhatsAppSettings.vue'
|
import WhatsAppSettings from '@/components/Settings/WhatsAppSettings.vue'
|
||||||
@ -88,7 +88,7 @@ const tabs = computed(() => {
|
|||||||
{
|
{
|
||||||
label: __('General'),
|
label: __('General'),
|
||||||
icon: 'settings',
|
icon: 'settings',
|
||||||
component: markRaw(GeneralSettings),
|
component: markRaw(GeneralSettingsPage),
|
||||||
condition: () => isManager(),
|
condition: () => isManager(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user