diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 5338837c..f4b87366 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -100,6 +100,7 @@ jobs: bench --site lms.test execute frappe.utils.install.complete_setup_wizard bench --site lms.test execute frappe.tests.ui_test_helpers.create_test_user bench --site lms.test set-password frappe@example.com admin + bench --site lms.test execute lms.lms.utils.persona_captured - name: cypress pre-requisites run: | diff --git a/cypress.config.js b/cypress.config.js index 5e1c68ea..c7c1354e 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -13,6 +13,6 @@ module.exports = defineConfig({ openMode: 0, }, e2e: { - baseUrl: "http://testui:8000", + baseUrl: "http://pertest:8000", }, }); diff --git a/cypress/e2e/course_creation.cy.js b/cypress/e2e/course_creation.cy.js index 69c0f1ca..28b97041 100644 --- a/cypress/e2e/course_creation.cy.js +++ b/cypress/e2e/course_creation.cy.js @@ -19,13 +19,6 @@ describe("Course Creation", () => { ); cy.fixture("profile.png", "base64").then((fileContent) => { - /* cy.get('input[type="file"]').should("be.hidden").attachFile({ - fileContent, - fileName: "profile.png", - mimeType: "image/png", - encoding: "base64", - }); */ - cy.get("div") .contains("Course Image") .siblings("div") diff --git a/frappe-ui b/frappe-ui index 29307e4f..8cd9b06a 160000 --- a/frappe-ui +++ b/frappe-ui @@ -1 +1 @@ -Subproject commit 29307e4fffaacdbb3d9c5d95c5270b2f245a5607 +Subproject commit 8cd9b06a5ed50dc181d9672b2fe84c1594b52b48 diff --git a/frontend/src/App.vue b/frontend/src/App.vue index d890f55a..c79397af 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -24,7 +24,7 @@ const router = useRouter() const noSidebar = ref(false) router.beforeEach((to, from, next) => { - if (to.query.fromLesson) { + if (to.query.fromLesson || to.path === '/persona') { noSidebar.value = true } else { noSidebar.value = false diff --git a/frontend/src/components/AppSidebar.vue b/frontend/src/components/AppSidebar.vue index 50c4f318..0dcc59f0 100644 --- a/frontend/src/components/AppSidebar.vue +++ b/frontend/src/components/AppSidebar.vue @@ -76,7 +76,7 @@ />
{ icon: 'LogIn', fields: [ { - label: 'Identify User Persona', + label: 'Identify User Category', name: 'user_category', type: 'checkbox', description: - 'Enable this option to identify the user persona during signup.', + 'Enable this option to identify the user category during signup.', }, { label: 'Disable signup', diff --git a/frontend/src/pages/Courses.vue b/frontend/src/pages/Courses.vue index bf8d4ec2..58b4717a 100644 --- a/frontend/src/pages/Courses.vue +++ b/frontend/src/pages/Courses.vue @@ -96,6 +96,7 @@ import { Breadcrumbs, Button, + call, createListResource, FormControl, Select, @@ -107,6 +108,7 @@ import { BookOpen, Plus } from 'lucide-vue-next' import { sessionStore } from '@/stores/session' import { canCreateCourse } from '@/utils' import CourseCard from '@/components/CourseCard.vue' +import router from '../router' const user = inject('$user') const dayjs = inject('$dayjs') @@ -121,6 +123,7 @@ const currentTab = ref('Live') const { brand } = sessionStore() onMounted(() => { + identifyUserPersona() setFiltersFromQuery() updateCourses() categories.value = [ @@ -145,16 +148,52 @@ const courses = createListResource({ pageLength: pageLength.value, start: start.value, onSuccess(data) { - let allCategories = data.map((course) => course.category) - allCategories = allCategories.filter( - (category, index) => allCategories.indexOf(category) === index && category - ) - if (categories.value.length <= allCategories.length) { - updateCategories(data) - } + setCategories(data) }, }) +const setCategories = (data) => { + let allCategories = data.map((course) => course.category) + allCategories = allCategories.filter( + (category, index) => allCategories.indexOf(category) === index && category + ) + if (categories.value.length <= allCategories.length) { + updateCategories(data) + } +} + +const isPersonaCaptured = async () => { + let persona = await call('frappe.client.get_single_value', { + doctype: 'LMS Settings', + field: 'persona_captured', + }) + return persona +} + +const identifyUserPersona = async () => { + let personaCaptured = await isPersonaCaptured() + debugger + console.log('personaCaptured', personaCaptured) + console.log('user.data?.is_system_manager', user.data?.is_system_manager) + console.log('user.data?.developer_mode', user.data?.developer_mode) + + if ( + user.data?.is_system_manager && + !user.data?.developer_mode && + !personaCaptured + ) { + call('frappe.client.get_count', { + doctype: 'LMS Course', + }).then((data) => { + if (!data) { + router.push({ + name: 'PersonaForm', + }) + } + }) + } +} + const updateCourses = () => { updateFilters() courses.update({ diff --git a/frontend/src/pages/PersonaForm.vue b/frontend/src/pages/PersonaForm.vue new file mode 100644 index 00000000..0ba7cf4d --- /dev/null +++ b/frontend/src/pages/PersonaForm.vue @@ -0,0 +1,199 @@ + + diff --git a/frontend/src/router.js b/frontend/src/router.js index 7eba6f7a..fb04cc7d 100644 --- a/frontend/src/router.js +++ b/frontend/src/router.js @@ -210,6 +210,11 @@ const routes = [ name: 'AssignmentSubmissionList', component: () => import('@/pages/AssignmentSubmissionList.vue'), }, + { + path: '/persona', + name: 'PersonaForm', + component: () => import('@/pages/PersonaForm.vue'), + }, ] let router = createRouter({ diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 4be6085e..16881bc4 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -25,7 +25,7 @@ export default defineConfig({ }), ], server: { - allowedHosts: ['fs', 'bs'], + allowedHosts: ['fs', 'persona'], }, resolve: { alias: { diff --git a/lms/lms/api.py b/lms/lms/api.py index cc8f7df0..1a133532 100644 --- a/lms/lms/api.py +++ b/lms/lms/api.py @@ -184,9 +184,10 @@ def get_user_info(): ) user.is_fc_site = is_fc_site() user.is_system_manager = "System Manager" in user.roles + user.sitename = frappe.local.site + user.developer_mode = frappe.conf.developer_mode if user.is_fc_site and user.is_system_manager: user.site_info = current_site_info() - user.sitename = frappe.local.site return user @@ -678,13 +679,13 @@ def get_categories(doctype, filters): @frappe.whitelist() def get_members(start=0, search=""): """Get members for the given search term and start index. - Args: start (int): Start index for the query. + Args: start (int): Start index for the query. <<<<<<< HEAD - search (str): Search term to filter the results. + search (str): Search term to filter the results. ======= - search (str): Search term to filter the results. + search (str): Search term to filter the results. >>>>>>> 4869bba7bbb2fb38477d6fc29fb3b5838e075577 - Returns: List of members. + Returns: List of members. """ filters = {"enabled": 1, "name": ["not in", ["Administrator", "Guest"]]} @@ -1389,3 +1390,17 @@ def add_an_evaluator(email): evaluator.insert() return evaluator + + +@frappe.whitelist() +def capture_user_persona(responses): + frappe.only_for("System Manager") + data = frappe.parse_json(responses) + data = json.dumps(data) + response = frappe.integrations.utils.make_post_request( + "https://school.frappe.io/api/method/capture-persona", + data={"response": data}, + ) + if response.get("message").get("name"): + frappe.db.set_single_value("LMS Settings", "persona_captured", True) + return response diff --git a/lms/lms/doctype/lms_settings/lms_settings.json b/lms/lms/doctype/lms_settings/lms_settings.json index 772a6fbe..8bf72de4 100644 --- a/lms/lms/doctype/lms_settings/lms_settings.json +++ b/lms/lms/doctype/lms_settings/lms_settings.json @@ -8,6 +8,7 @@ "general_tab", "default_home", "send_calendar_invite_for_evaluations", + "persona_captured", "column_break_zdel", "allow_guest_access", "enable_learning_paths", @@ -108,7 +109,7 @@ "default": "0", "fieldname": "user_category", "fieldtype": "Check", - "label": "Identify User Persona" + "label": "Identify User Category" }, { "default": "0", @@ -380,6 +381,10 @@ "fieldtype": "Attach Image", "label": "Meta Image" }, + { + "fieldname": "column_break_xijv", + "fieldtype": "Column Break" + }, { "description": "Common keywords that will be used for all pages", "fieldname": "meta_keywords", @@ -387,15 +392,18 @@ "label": "Meta Keywords" }, { - "fieldname": "column_break_xijv", - "fieldtype": "Column Break" + "default": "0", + "fieldname": "persona_captured", + "fieldtype": "Check", + "label": "Persona Captured", + "read_only": 1 } ], "grid_page_length": 50, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2025-04-19 12:19:24.037931", + "modified": "2025-04-22 16:05:27.914422", "modified_by": "sayali@frappe.io", "module": "LMS", "name": "LMS Settings", diff --git a/lms/lms/utils.py b/lms/lms/utils.py index 9a39b4a9..83e219ec 100644 --- a/lms/lms/utils.py +++ b/lms/lms/utils.py @@ -2167,3 +2167,7 @@ def get_palette(full_name): hash_name = hashlib.md5(encoded_name).hexdigest() idx = cint((int(hash_name[4:6], 16) + 1) / 5.33) return palette[idx % 8] + + +def persona_captured(): + frappe.db.set_single_value("LMS Settings", "persona_captured", 1)