refactor: telemetry
* only works with frappe v15.96+
This commit is contained in:
@@ -15,7 +15,6 @@ import { useScreenSize } from './utils/composables'
|
||||
import { usersStore } from '@/stores/user'
|
||||
import { useSettings } from '@/stores/settings'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { posthogSettings } from '@/telemetry'
|
||||
import DesktopLayout from './components/DesktopLayout.vue'
|
||||
import MobileLayout from './components/MobileLayout.vue'
|
||||
import NoSidebarLayout from './components/NoSidebarLayout.vue'
|
||||
@@ -50,9 +49,4 @@ onUnmounted(() => {
|
||||
noSidebar.value = false
|
||||
})
|
||||
|
||||
watch(userResource, () => {
|
||||
if (userResource.data) {
|
||||
posthogSettings.reload()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -189,15 +189,16 @@ import {
|
||||
import { computed, inject, ref } from 'vue'
|
||||
import { Badge, Button, call, createResource, toast } from 'frappe-ui'
|
||||
import { formatAmount } from '@/utils/'
|
||||
import { capture } from '@/telemetry'
|
||||
import { useRouter } from 'vue-router'
|
||||
import CertificationLinks from '@/components/CertificationLinks.vue'
|
||||
import CourseProgressSummary from '@/components/Modals/CourseProgressSummary.vue'
|
||||
import { useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
const router = useRouter()
|
||||
const user = inject('$user')
|
||||
const showProgressModal = ref(false)
|
||||
const readOnlyMode = window.read_only_mode
|
||||
const { capture } = useTelemetry()
|
||||
|
||||
const props = defineProps({
|
||||
course: {
|
||||
@@ -284,6 +285,9 @@ const certificate = createResource({
|
||||
}&format=${encodeURIComponent(data.template)}`,
|
||||
'_blank'
|
||||
)
|
||||
capture('certificate_issued', {
|
||||
course: props.course.data.name,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -80,13 +80,13 @@ import {
|
||||
} from 'frappe-ui'
|
||||
import { reactive, watch, inject } from 'vue'
|
||||
import { getFileSize } from '@/utils/'
|
||||
import { capture } from '@/telemetry'
|
||||
import { FileText, X } from 'lucide-vue-next'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
const show = defineModel()
|
||||
const outline = defineModel('outline')
|
||||
const user = inject('$user')
|
||||
const { capture } = useTelemetry()
|
||||
const { updateOnboardingStep } = useOnboarding('learning')
|
||||
|
||||
const props = defineProps({
|
||||
|
||||
@@ -66,6 +66,7 @@ import { inject, reactive, watch } from 'vue'
|
||||
import { User } from '@/components/Settings/types'
|
||||
import { openSettings, cleanError } from '@/utils'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import { useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
interface ZoomAccount {
|
||||
name: string
|
||||
@@ -97,6 +98,7 @@ interface ZoomAccounts {
|
||||
const show = defineModel('show')
|
||||
const user = inject<User | null>('$user')
|
||||
const zoomAccounts = defineModel<ZoomAccounts>('zoomAccounts')
|
||||
const { capture } = useTelemetry()
|
||||
|
||||
const account = reactive({
|
||||
name: '',
|
||||
@@ -154,6 +156,7 @@ const createAccount = (close: () => void) => {
|
||||
},
|
||||
{
|
||||
onSuccess() {
|
||||
capture('zoom_account_linked')
|
||||
zoomAccounts.value?.reload()
|
||||
close()
|
||||
toast.success(__('Zoom Account created successfully'))
|
||||
|
||||
@@ -52,12 +52,14 @@ import {
|
||||
} from 'frappe-ui'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import SettingFields from '@/components/Settings/SettingFields.vue'
|
||||
import { useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
const show = defineModel<boolean>({ required: true, default: false })
|
||||
const paymentGateways = defineModel<any>('paymentGateways')
|
||||
const newGateway = ref(null)
|
||||
const newGatewayFields = ref([])
|
||||
const newGatewayData = ref<Record<string, any>>({})
|
||||
const { capture } = useTelemetry()
|
||||
|
||||
const props = defineProps<{
|
||||
gatewayID: string | null
|
||||
@@ -158,6 +160,7 @@ const saveNewGateway = (close: () => void) => {
|
||||
...newGatewayData.value,
|
||||
},
|
||||
}).then((data: any) => {
|
||||
capture('payment_gateway_configured')
|
||||
paymentGateways.value.reload()
|
||||
close()
|
||||
})
|
||||
|
||||
@@ -199,7 +199,6 @@ import { useSidebar } from '@/stores/sidebar'
|
||||
import { useSettings } from '@/stores/settings'
|
||||
import { Button, call, createResource, Tooltip, toast } from 'frappe-ui'
|
||||
import PageModal from '@/components/Modals/PageModal.vue'
|
||||
import { capture } from '@/telemetry'
|
||||
import LMSLogo from '@/components/Icons/LMSLogo.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import {
|
||||
@@ -233,6 +232,7 @@ import {
|
||||
showHelpModal,
|
||||
minimize,
|
||||
IntermediateStepModal,
|
||||
useTelemetry,
|
||||
} from 'frappe-ui/frappe'
|
||||
import InviteIcon from '@/components/Icons/InviteIcon.vue'
|
||||
import UserDropdown from '@/components/Sidebar/UserDropdown.vue'
|
||||
@@ -246,6 +246,7 @@ let sidebarStore = useSidebar()
|
||||
const socket = inject('$socket')
|
||||
const unreadCount = ref(0)
|
||||
const sidebarLinks = ref(null)
|
||||
const { capture } = useTelemetry()
|
||||
const showPageModal = ref(false)
|
||||
const isModerator = ref(false)
|
||||
const isInstructor = ref(false)
|
||||
|
||||
@@ -9,6 +9,7 @@ import translationPlugin from './translation'
|
||||
import { usersStore } from './stores/user'
|
||||
import { initSocket } from './socket'
|
||||
import { FrappeUI, setConfig, frappeRequest, pageMetaPlugin } from 'frappe-ui'
|
||||
import { telemetryPlugin } from 'frappe-ui/frappe'
|
||||
|
||||
let pinia = createPinia()
|
||||
let app = createApp(App)
|
||||
@@ -18,6 +19,7 @@ app.use(FrappeUI)
|
||||
app.use(pinia)
|
||||
app.use(router)
|
||||
app.use(translationPlugin)
|
||||
app.use(telemetryPlugin, { app_name: 'lms' })
|
||||
app.use(pageMetaPlugin)
|
||||
app.provide('$dayjs', dayjs)
|
||||
app.provide('$socket', initSocket())
|
||||
|
||||
@@ -292,8 +292,7 @@ import {
|
||||
} from 'frappe-ui'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { Image, Trash2 } from 'lucide-vue-next'
|
||||
import { capture } from '@/telemetry'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
import { sessionStore } from '../stores/session'
|
||||
import MultiSelect from '@/components/Controls/MultiSelect.vue'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
@@ -312,6 +311,7 @@ const { brand } = sessionStore()
|
||||
const { updateOnboardingStep } = useOnboarding('learning')
|
||||
const instructors = ref([])
|
||||
const app = getCurrentInstance()
|
||||
const { capture } = useTelemetry()
|
||||
const { $dialog } = app.appContext.config.globalProperties
|
||||
|
||||
const props = defineProps({
|
||||
|
||||
@@ -234,10 +234,12 @@ import { sessionStore } from '../stores/session'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import NotPermitted from '@/components/NotPermitted.vue'
|
||||
import { X } from 'lucide-vue-next'
|
||||
import { useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
const user = inject('$user')
|
||||
const { brand } = sessionStore()
|
||||
const showConsentWarning = ref(false)
|
||||
const { capture } = useTelemetry()
|
||||
|
||||
onMounted(() => {
|
||||
const script = document.createElement('script')
|
||||
@@ -339,6 +341,7 @@ const generatePaymentLink = () => {
|
||||
return validateAddress()
|
||||
},
|
||||
onSuccess(data) {
|
||||
capture('checkout_initiated', { type: props.type })
|
||||
window.location.href = data
|
||||
},
|
||||
onError(err) {
|
||||
|
||||
@@ -349,8 +349,7 @@ import {
|
||||
} from 'vue'
|
||||
import { Image, Trash2, X } from 'lucide-vue-next'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { capture, startRecording, stopRecording } from '@/telemetry'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
import { sessionStore } from '../stores/session'
|
||||
import {
|
||||
escapeHTML,
|
||||
@@ -372,6 +371,7 @@ const router = useRouter()
|
||||
const instructors = ref([])
|
||||
const related_courses = ref([])
|
||||
const app = getCurrentInstance()
|
||||
const { capture } = useTelemetry()
|
||||
const { updateOnboardingStep } = useOnboarding('learning')
|
||||
const { $dialog } = app.appContext.config.globalProperties
|
||||
|
||||
@@ -418,7 +418,6 @@ onMounted(() => {
|
||||
fetchCourseInfo()
|
||||
} else {
|
||||
capture('course_form_opened')
|
||||
startRecording()
|
||||
}
|
||||
window.addEventListener('keydown', keyboardShortcut)
|
||||
})
|
||||
@@ -441,7 +440,6 @@ const keyboardShortcut = (e) => {
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('keydown', keyboardShortcut)
|
||||
stopRecording()
|
||||
})
|
||||
|
||||
const courseCreationResource = createResource({
|
||||
@@ -582,12 +580,16 @@ const createCourse = () => {
|
||||
}
|
||||
|
||||
const editCourse = () => {
|
||||
let was_published = courseResource.data.published
|
||||
courseEditResource.submit(
|
||||
{
|
||||
course: courseResource.data.name,
|
||||
},
|
||||
{
|
||||
onSuccess() {
|
||||
if (!was_published && course.published) {
|
||||
capture('publish_course')
|
||||
}
|
||||
updateMetaInfo('courses', props.courseName, meta)
|
||||
toast.success(__('Course updated successfully'))
|
||||
},
|
||||
|
||||
@@ -99,14 +99,14 @@ import EditorJS from '@editorjs/editorjs'
|
||||
import LessonHelp from '@/components/LessonHelp.vue'
|
||||
import { ChevronRight } from 'lucide-vue-next'
|
||||
import { getEditorTools, enablePlyr } from '@/utils'
|
||||
import { capture, startRecording, stopRecording } from '@/telemetry'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
const { brand } = sessionStore()
|
||||
const editor = ref(null)
|
||||
const instructorEditor = ref(null)
|
||||
const user = inject('$user')
|
||||
const openInstructorEditor = ref(false)
|
||||
const { capture } = useTelemetry()
|
||||
const { updateOnboardingStep } = useOnboarding('learning')
|
||||
let autoSaveInterval
|
||||
let showSuccessMessage = false
|
||||
@@ -131,7 +131,6 @@ onMounted(() => {
|
||||
window.location.href = '/login'
|
||||
}
|
||||
capture('lesson_form_opened')
|
||||
startRecording()
|
||||
editor.value = renderEditor('content')
|
||||
instructorEditor.value = renderEditor('instructor-notes')
|
||||
window.addEventListener('keydown', keyboardShortcut)
|
||||
@@ -226,7 +225,6 @@ const keyboardShortcut = (e) => {
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(autoSaveInterval)
|
||||
window.removeEventListener('keydown', keyboardShortcut)
|
||||
stopRecording()
|
||||
})
|
||||
|
||||
const newLessonResource = createResource({
|
||||
|
||||
@@ -233,6 +233,7 @@ import { ClipboardList, ListChecks, Plus, Trash2 } from 'lucide-vue-next'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { escapeHTML } from '@/utils'
|
||||
import Question from '@/components/Modals/Question.vue'
|
||||
import { useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
const { brand } = sessionStore()
|
||||
const showQuestionModal = ref(false)
|
||||
@@ -241,6 +242,7 @@ const currentQuestion = reactive({
|
||||
marks: 0,
|
||||
name: '',
|
||||
})
|
||||
const { capture } = useTelemetry()
|
||||
const user = inject('$user')
|
||||
const router = useRouter()
|
||||
const readOnlyMode = window.read_only_mode
|
||||
@@ -308,6 +310,9 @@ const submitQuiz = () => {
|
||||
},
|
||||
{
|
||||
onSuccess(data) {
|
||||
if (props.quizID === 'new') {
|
||||
capture('quiz_created')
|
||||
}
|
||||
quizDetails.doc.total_marks = data.total_marks
|
||||
toast.success(__('Quiz updated successfully'))
|
||||
},
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
import '../../../frappe/frappe/public/js/lib/posthog.js'
|
||||
import { createResource } from 'frappe-ui'
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
posthog: any
|
||||
}
|
||||
}
|
||||
|
||||
type PosthogSettings = {
|
||||
posthog_project_id: string
|
||||
posthog_host: string
|
||||
enable_telemetry: boolean
|
||||
telemetry_site_age: number
|
||||
}
|
||||
|
||||
interface CaptureOptions {
|
||||
data: {
|
||||
user: string
|
||||
[key: string]: string | number | boolean | object
|
||||
}
|
||||
}
|
||||
|
||||
let posthog: typeof window.posthog = window.posthog
|
||||
|
||||
// Posthog Settings
|
||||
let posthogSettings = createResource({
|
||||
url: 'lms.lms.telemetry.get_posthog_settings',
|
||||
cache: 'posthog_settings',
|
||||
onSuccess: (ps: PosthogSettings) => initPosthog(ps),
|
||||
})
|
||||
|
||||
let isTelemetryEnabled = () => {
|
||||
if (!posthogSettings.data) return false
|
||||
|
||||
return (
|
||||
posthogSettings.data.enable_telemetry &&
|
||||
posthogSettings.data.posthog_project_id &&
|
||||
posthogSettings.data.posthog_host
|
||||
)
|
||||
}
|
||||
|
||||
// Posthog Initialization
|
||||
function initPosthog(ps: PosthogSettings) {
|
||||
if (!isTelemetryEnabled()) return
|
||||
|
||||
posthog.init(ps.posthog_project_id, {
|
||||
api_host: ps.posthog_host,
|
||||
person_profiles: 'identified_only',
|
||||
autocapture: false,
|
||||
capture_pageview: true,
|
||||
capture_pageleave: true,
|
||||
enable_heatmaps: false,
|
||||
disable_session_recording: false,
|
||||
loaded: (ph: typeof posthog) => {
|
||||
window.posthog = ph
|
||||
ph.identify(window.location.hostname)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Posthog Functions
|
||||
function capture(
|
||||
event: string,
|
||||
options: CaptureOptions = { data: { user: '' } },
|
||||
) {
|
||||
if (!isTelemetryEnabled()) return
|
||||
window.posthog.capture(`lms_${event}`, options)
|
||||
}
|
||||
|
||||
function startRecording() {
|
||||
}
|
||||
|
||||
function stopRecording() {
|
||||
}
|
||||
|
||||
// Posthog Plugin
|
||||
function posthogPlugin(app: any) {
|
||||
app.config.globalProperties.posthog = posthog
|
||||
if (!window.posthog?.length) posthogSettings.fetch()
|
||||
}
|
||||
|
||||
export {
|
||||
posthog,
|
||||
posthogSettings,
|
||||
posthogPlugin,
|
||||
capture,
|
||||
startRecording,
|
||||
stopRecording,
|
||||
}
|
||||
Reference in New Issue
Block a user