Merge pull request #444 from shariquerik/saas-signup
feat: SaaS Billing page
This commit is contained in:
commit
8f312b02bf
@ -3,6 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cint
|
||||
from frappe.utils.telemetry import capture
|
||||
|
||||
no_cache = 1
|
||||
@ -32,6 +33,7 @@ def get_boot():
|
||||
"site_name": frappe.local.site,
|
||||
"read_only_mode": frappe.flags.read_only,
|
||||
"csrf_token": frappe.sessions.get_csrf_token(),
|
||||
"setup_complete": cint(frappe.get_system_settings("setup_complete"))
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit b2dbd41936905aa46b18d3c22e5d09a7b08a9b98
|
||||
Subproject commit ee1e7d915a3147d387c419cd317d5982d060fd14
|
||||
@ -14,7 +14,7 @@
|
||||
"@vueuse/core": "^10.3.0",
|
||||
"@vueuse/integrations": "^10.3.0",
|
||||
"feather-icons": "^4.28.0",
|
||||
"frappe-ui": "^0.1.71",
|
||||
"frappe-ui": "^0.1.74",
|
||||
"gemoji": "^8.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mime": "^4.0.1",
|
||||
@ -22,7 +22,6 @@
|
||||
"socket.io-client": "^4.7.2",
|
||||
"sortablejs": "^1.15.0",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"vite": "^4.4.9",
|
||||
"vue": "^3.4.12",
|
||||
"vue-router": "^4.2.2",
|
||||
"vuedraggable": "^4.1.0"
|
||||
|
||||
@ -12,11 +12,11 @@ import { sessionStore as session } from '@/stores/session'
|
||||
import { Toasts } from 'frappe-ui'
|
||||
import { computed, defineAsyncComponent } from 'vue'
|
||||
|
||||
const MobileLayout = defineAsyncComponent(() =>
|
||||
import('./components/Layouts/MobileLayout.vue')
|
||||
const MobileLayout = defineAsyncComponent(
|
||||
() => import('./components/Layouts/MobileLayout.vue'),
|
||||
)
|
||||
const DesktopLayout = defineAsyncComponent(() =>
|
||||
import('./components/Layouts/DesktopLayout.vue')
|
||||
const DesktopLayout = defineAsyncComponent(
|
||||
() => import('./components/Layouts/DesktopLayout.vue'),
|
||||
)
|
||||
const Layout = computed(() => {
|
||||
if (window.innerWidth < 640) {
|
||||
|
||||
@ -71,6 +71,7 @@
|
||||
</Section>
|
||||
</div>
|
||||
</div>
|
||||
<TrialBanner v-if="isFCSite.data" />
|
||||
<div class="m-2 flex flex-col gap-1">
|
||||
<SidebarLink
|
||||
:label="isSidebarCollapsed ? __('Expand') : __('Collapse')"
|
||||
@ -89,6 +90,7 @@
|
||||
</SidebarLink>
|
||||
</div>
|
||||
<Notifications />
|
||||
<Settings />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -108,14 +110,15 @@ import CollapseSidebar from '@/components/Icons/CollapseSidebar.vue'
|
||||
import NotificationsIcon from '@/components/Icons/NotificationsIcon.vue'
|
||||
import SidebarLink from '@/components/SidebarLink.vue'
|
||||
import Notifications from '@/components/Notifications.vue'
|
||||
import Settings from '@/components/Settings/Settings.vue'
|
||||
import { viewsStore } from '@/stores/views'
|
||||
import {
|
||||
unreadNotificationsCount,
|
||||
notificationsStore,
|
||||
} from '@/stores/notifications'
|
||||
import { FeatherIcon } from 'frappe-ui'
|
||||
import { FeatherIcon, TrialBanner, createResource } from 'frappe-ui'
|
||||
import { useStorage } from '@vueuse/core'
|
||||
import { computed, h } from 'vue'
|
||||
import { computed, h, provide } from 'vue'
|
||||
|
||||
const { getPinnedViews, getPublicViews } = viewsStore()
|
||||
const { toggle: toggleNotificationPanel } = notificationsStore()
|
||||
@ -226,4 +229,13 @@ function getIcon(routeName, icon) {
|
||||
return PinIcon
|
||||
}
|
||||
}
|
||||
|
||||
const isFCSite = createResource({
|
||||
url: 'frappe.integrations.frappe_providers.frappecloud_billing.is_fc_site',
|
||||
cache: 'isFCSite',
|
||||
auto: true,
|
||||
transform: (data) => Boolean(data),
|
||||
})
|
||||
|
||||
provide('isFCSite', isFCSite)
|
||||
</script>
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<Dialog v-model="show" :options="{ size: '5xl' }">
|
||||
<Dialog
|
||||
v-model="showSettings"
|
||||
:options="{ size: '5xl' }"
|
||||
@close="activeSettingsPage = ''"
|
||||
>
|
||||
<template #body>
|
||||
<div class="flex h-[calc(100vh_-_8rem)]">
|
||||
<div class="flex w-52 shrink-0 flex-col bg-gray-50 p-2">
|
||||
@ -47,11 +51,16 @@ import WhatsAppSettings from '@/components/Settings/WhatsAppSettings.vue'
|
||||
import ERPNextSettings from '@/components/Settings/ERPNextSettings.vue'
|
||||
import TwilioSettings from '@/components/Settings/TwilioSettings.vue'
|
||||
import SidebarLink from '@/components/SidebarLink.vue'
|
||||
import { isWhatsappInstalled } from '@/composables/settings'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import {
|
||||
isWhatsappInstalled,
|
||||
showSettings,
|
||||
activeSettingsPage,
|
||||
} from '@/composables/settings'
|
||||
import { Dialog } from 'frappe-ui'
|
||||
import { ref, markRaw, computed, h } from 'vue'
|
||||
import { ref, markRaw, computed, watch } from 'vue'
|
||||
|
||||
const show = defineModel()
|
||||
const { isManager } = usersStore()
|
||||
|
||||
const tabs = computed(() => {
|
||||
let _tabs = [
|
||||
@ -68,6 +77,7 @@ const tabs = computed(() => {
|
||||
label: __('Invite Members'),
|
||||
icon: 'user-plus',
|
||||
component: markRaw(InviteMemberPage),
|
||||
condition: () => isManager(),
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -94,16 +104,29 @@ const tabs = computed(() => {
|
||||
},
|
||||
]
|
||||
|
||||
return _tabs.map((tab) => {
|
||||
tab.items = tab.items.filter((item) => {
|
||||
if (item.condition) {
|
||||
return item.condition()
|
||||
}
|
||||
return true
|
||||
})
|
||||
return tab
|
||||
return _tabs.filter((tab) => {
|
||||
if (tab.condition && !tab.condition()) return false
|
||||
if (tab.items) {
|
||||
tab.items = tab.items.filter((item) => {
|
||||
if (item.condition && !item.condition()) return false
|
||||
return true
|
||||
})
|
||||
}
|
||||
return true
|
||||
})
|
||||
})
|
||||
|
||||
const activeTab = ref(tabs.value[0].items[0])
|
||||
|
||||
function setActiveTab(tabName) {
|
||||
activeTab.value =
|
||||
(tabName &&
|
||||
tabs.value
|
||||
.map((tab) => tab.items)
|
||||
.flat()
|
||||
.find((tab) => tab.label === tabName)) ||
|
||||
tabs.value[0].items[0]
|
||||
}
|
||||
|
||||
watch(activeSettingsPage, (activePage) => setActiveTab(activePage))
|
||||
</script>
|
||||
@ -44,17 +44,16 @@
|
||||
</button>
|
||||
</template>
|
||||
</Dropdown>
|
||||
<SettingsModal v-if="showSettingsModal" v-model="showSettingsModal" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SettingsModal from '@/components/Settings/SettingsModal.vue'
|
||||
import CRMLogo from '@/components/Icons/CRMLogo.vue'
|
||||
import Apps from '@/components/Apps.vue'
|
||||
import { sessionStore } from '@/stores/session'
|
||||
import { usersStore } from '@/stores/users'
|
||||
import { showSettings } from '@/composables/settings'
|
||||
import { Dropdown } from 'frappe-ui'
|
||||
import { computed, ref, markRaw} from 'vue'
|
||||
import { computed, ref, markRaw, inject } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
isCollapsed: {
|
||||
@ -68,7 +67,7 @@ const { getUser } = usersStore()
|
||||
|
||||
const user = computed(() => getUser() || {})
|
||||
|
||||
const showSettingsModal = ref(false)
|
||||
const isFCSite = inject('isFCSite')
|
||||
|
||||
let dropdownOptions = ref([
|
||||
{
|
||||
@ -94,10 +93,16 @@ let dropdownOptions = ref([
|
||||
group: 'Others',
|
||||
hideLabel: true,
|
||||
items: [
|
||||
{
|
||||
icon: 'credit-card',
|
||||
label: computed(() => __('Billing')),
|
||||
onClick: () => (window.location.href = '/billing'),
|
||||
condition: () => isFCSite.data,
|
||||
},
|
||||
{
|
||||
icon: 'settings',
|
||||
label: computed(() => __('Settings')),
|
||||
onClick: () => (showSettingsModal.value = true),
|
||||
onClick: () => (showSettings.value = true),
|
||||
},
|
||||
{
|
||||
icon: 'log-out',
|
||||
|
||||
@ -33,3 +33,6 @@ createResource({
|
||||
export const mobileSidebarOpened = ref(false)
|
||||
|
||||
export const isMobileView = computed(() => window.innerWidth < 768)
|
||||
|
||||
export const showSettings = ref(false)
|
||||
export const activeSettingsPage = ref('')
|
||||
|
||||
@ -35,7 +35,7 @@ export const sessionStore = defineStore('crm-session', () => {
|
||||
onSuccess() {
|
||||
userResource.reset()
|
||||
user.value = null
|
||||
router.replace({ name: 'Home' })
|
||||
window.location.href = '/login?redirect-to=/crm'
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@ -3780,11 +3780,6 @@ human-signals@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28"
|
||||
integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==
|
||||
|
||||
husky@>=6:
|
||||
version "9.1.6"
|
||||
resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.6.tgz#e23aa996b6203ab33534bdc82306b0cf2cb07d6c"
|
||||
integrity sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user