diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index 6a9d4d5b8..e7dfc8dc5 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -8,10 +8,12 @@
diff --git a/frontend/src/components/BatchOverlay.vue b/frontend/src/components/BatchOverlay.vue
index 2eb225c22..670548a41 100644
--- a/frontend/src/components/BatchOverlay.vue
+++ b/frontend/src/components/BatchOverlay.vue
@@ -81,7 +81,7 @@
{
if (!user.data) window.location.href = '/login'
if (props.batchName != 'new') {
batchDetail.reload()
+ } else {
+ capture("batch_form_opened")
}
window.addEventListener('keydown', keyboardShortcut)
})
@@ -377,6 +380,7 @@ const createNewBatch = () => {
{},
{
onSuccess(data) {
+ capture("batch_created")
router.push({
name: 'BatchDetail',
params: {
@@ -447,7 +451,7 @@ const breadcrumbs = computed(() => {
}
crumbs.push({
label: props.batchName == 'new' ? 'New Batch' : 'Edit Batch',
- route: { name: 'BatchCreation', params: { batchName: props.batchName } },
+ route: { name: 'BatchForm', params: { batchName: props.batchName } },
})
return crumbs
})
diff --git a/frontend/src/pages/Batches.vue b/frontend/src/pages/Batches.vue
index 2ace50f69..77e73c5d4 100644
--- a/frontend/src/pages/Batches.vue
+++ b/frontend/src/pages/Batches.vue
@@ -19,7 +19,7 @@
diff --git a/frontend/src/pages/CreateCourse.vue b/frontend/src/pages/CourseForm.vue
similarity index 98%
rename from frontend/src/pages/CreateCourse.vue
rename to frontend/src/pages/CourseForm.vue
index dbd33dda1..4e92db901 100644
--- a/frontend/src/pages/CreateCourse.vue
+++ b/frontend/src/pages/CourseForm.vue
@@ -227,6 +227,7 @@ import { FileText, X } from 'lucide-vue-next'
import { useRouter } from 'vue-router'
import CourseOutline from '@/components/CourseOutline.vue'
import MultiSelect from '@/components/Controls/MultiSelect.vue'
+import { capture } from "@/telemetry";
const user = inject('$user')
const newTag = ref('')
@@ -268,6 +269,8 @@ onMounted(() => {
if (props.courseName !== 'new') {
courseResource.reload()
+ } else {
+ capture("course_form_opened")
}
window.addEventListener('keydown', keyboardShortcut)
})
@@ -388,9 +391,10 @@ const submitCourse = () => {
} else {
courseCreationResource.submit(course, {
onSuccess(data) {
+ capture("course_created")
showToast('Success', 'Course created successfully', 'check')
router.push({
- name: 'CreateCourse',
+ name: 'CourseForm',
params: { courseName: data.name },
})
},
@@ -489,7 +493,7 @@ const breadcrumbs = computed(() => {
}
crumbs.push({
label: props.courseName == 'new' ? 'New Course' : 'Edit Course',
- route: { name: 'CreateCourse', params: { courseName: props.courseName } },
+ route: { name: 'CourseForm', params: { courseName: props.courseName } },
})
return crumbs
})
diff --git a/frontend/src/pages/Courses.vue b/frontend/src/pages/Courses.vue
index c367d1512..299cf4345 100644
--- a/frontend/src/pages/Courses.vue
+++ b/frontend/src/pages/Courses.vue
@@ -22,7 +22,7 @@
import('@/pages/CreateCourse.vue'),
+ name: 'CourseForm',
+ component: () => import('@/pages/CourseForm.vue'),
props: true,
},
{
@@ -109,8 +109,8 @@ const routes = [
},
{
path: '/batches/:batchName/edit',
- name: 'BatchCreation',
- component: () => import('@/pages/BatchCreation.vue'),
+ name: 'BatchForm',
+ component: () => import('@/pages/BatchForm.vue'),
props: true,
},
{
diff --git a/frontend/src/telemetry.ts b/frontend/src/telemetry.ts
new file mode 100644
index 000000000..dfd5e3b6a
--- /dev/null
+++ b/frontend/src/telemetry.ts
@@ -0,0 +1,98 @@
+import { useStorage } from "@vueuse/core";
+import { call } from "frappe-ui";
+import "../../../frappe/frappe/public/js/lib/posthog.js";
+
+const APP = "lms";
+const SITENAME = window.location.hostname;
+
+declare global {
+ interface Window {
+ posthog: any;
+ }
+}
+
+const telemetry = useStorage("telemetry", {
+ enabled: false,
+ project_id: "",
+ host: "",
+});
+
+export async function init() {
+ await set_enabled();
+ if (!telemetry.value.enabled) return;
+ try {
+ await set_credentials();
+ window.posthog.init(telemetry.value.project_id, {
+ api_host: telemetry.value.host,
+ autocapture: false,
+ person_profiles: "always",
+ capture_pageview: true,
+ capture_pageleave: true,
+ disable_session_recording: false,
+ session_recording: {
+ maskAllInputs: false,
+ maskInputOptions: {
+ password: true,
+ },
+ },
+ loaded: (posthog) => {
+ window.posthog = posthog;
+ window.posthog.identify(SITENAME);
+ },
+ });
+ } catch (e) {
+ console.trace("Failed to initialize telemetry", e);
+ telemetry.value.enabled = false;
+ }
+}
+
+async function set_enabled() {
+ if (telemetry.value.enabled) return;
+
+ await call("lms.lms.telemetry.is_enabled").then((res) => {
+ telemetry.value.enabled = res;
+ });
+}
+
+async function set_credentials() {
+ if (!telemetry.value.enabled) return;
+ if (telemetry.value.project_id && telemetry.value.host) return;
+
+ await call("lms.lms.telemetry.get_credentials").then((res) => {
+ telemetry.value.project_id = res.project_id;
+ telemetry.value.host = res.telemetry_host;
+ });
+}
+
+interface CaptureOptions {
+ data: {
+ user: string;
+ [key: string]: string | number | boolean | object;
+ };
+}
+
+export function capture(
+ event: string,
+ options: CaptureOptions = { data: { user: "" } }
+) {
+ if (!telemetry.value.enabled) return;
+ window.posthog.capture(`${APP}_${event}`, options);
+}
+
+export function recordSession() {
+ if (!telemetry.value.enabled) return;
+ if (window.posthog && window.posthog.__loaded) {
+ window.posthog.startSessionRecording();
+ }
+}
+
+export function stopSession() {
+ if (!telemetry.value.enabled) return;
+ if (
+ window.posthog &&
+ window.posthog.__loaded &&
+ window.posthog.sessionRecordingStarted()
+ ) {
+ window.posthog.stopSessionRecording();
+ }
+}
diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js
index e732e09f2..2123d981d 100644
--- a/frontend/src/utils/index.js
+++ b/frontend/src/utils/index.js
@@ -424,7 +424,7 @@ export function getSidebarLinks() {
'Courses',
'CourseDetail',
'Lesson',
- 'CreateCourse',
+ 'CourseForm',
'LessonForm',
],
},
@@ -432,7 +432,7 @@ export function getSidebarLinks() {
label: 'Batches',
icon: 'Users',
to: 'Batches',
- activeFor: ['Batches', 'BatchDetail', 'Batch', 'BatchCreation'],
+ activeFor: ['Batches', 'BatchDetail', 'Batch', 'BatchForm'],
},
{
label: 'Certified Participants',
diff --git a/lms/lms/api.py b/lms/lms/api.py
index a27557e75..c25e49da2 100644
--- a/lms/lms/api.py
+++ b/lms/lms/api.py
@@ -560,23 +560,3 @@ def get_categories(doctype, filters):
categoryOptions.append({"label": category, "value": category})
return categoryOptions
-
-@frappe.whitelist(allow_guest=True)
-def get_posthog_api_key():
- should_record_session
- return {
- "project_id": frappe.conf.get(POSTHOG_PROJECT_FIELD),
- "posthog_host": frappe.conf.get(POSTHOG_HOST_FIELD),
- "enable_telemetry": frappe.get_system_settings("enable_telemetry"),
- "should_record_session": should_record_session(),
- }
-
-def should_record_session():
- start_datetime = frappe.boot.sysdefaults.session_recording_start
- start_datetime = get_datetime(start_datetime)
- if not start_datetime:
- return False
-
- now = now_datetime()
- # if user allowed recording only record for first 2 hours, never again.
- return time_diff(now, start_datetime) < 120;
\ No newline at end of file
diff --git a/lms/lms/telemetry.py b/lms/lms/telemetry.py
new file mode 100644
index 000000000..c704351f3
--- /dev/null
+++ b/lms/lms/telemetry.py
@@ -0,0 +1,16 @@
+import frappe
+
+@frappe.whitelist()
+def is_enabled():
+ return bool(
+ frappe.get_system_settings("enable_telemetry")
+ and frappe.conf.get("posthog_host")
+ and frappe.conf.get("posthog_project_id")
+ )
+
+@frappe.whitelist()
+def get_credentials():
+ return {
+ "project_id": frappe.conf.get("posthog_project_id"),
+ "telemetry_host": frappe.conf.get("posthog_host"),
+ }
diff --git a/package.json b/package.json
index 3d55b554e..f5231fac1 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,6 @@
"cypress-file-upload": "^5.0.8"
},
"dependencies": {
- "posthog-js": "^1.154.4",
"pre-commit": "^1.2.2"
}
}