Merge pull request #444 from shariquerik/saas-signup

feat: SaaS Billing page
This commit is contained in:
Shariq Ansari 2024-11-19 11:46:11 +05:30 committed by GitHub
commit 8f312b02bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 71 additions and 32 deletions

View File

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

View File

@ -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"

View File

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

View File

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

View File

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

View File

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

View File

@ -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('')

View File

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

View File

@ -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"