feat: app switcher
This commit is contained in:
67
frontend/src/components/Apps.vue
Normal file
67
frontend/src/components/Apps.vue
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<template>
|
||||||
|
<Popover placement="right-start" class="flex w-full">
|
||||||
|
<template #target="{ togglePopover }">
|
||||||
|
<button
|
||||||
|
:class="[
|
||||||
|
'group w-full flex h-7 items-center justify-between rounded px-2 text-base text-gray-800 hover:bg-gray-100',
|
||||||
|
]"
|
||||||
|
@click.prevent="togglePopover()"
|
||||||
|
>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<LayoutGrid class="size-4 stroke-1.5" />
|
||||||
|
<span class="whitespace-nowrap">
|
||||||
|
{{ __('Apps') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ChevronRight class="h-4 w-4 stroke-1.5" />
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template #body>
|
||||||
|
<div
|
||||||
|
class="grid grid-cols-3 justify-between mx-3 p-2 rounded-lg border border-gray-100 bg-white shadow-xl"
|
||||||
|
>
|
||||||
|
<div v-for="app in apps.data" key="name">
|
||||||
|
<a
|
||||||
|
:href="app.route"
|
||||||
|
class="flex flex-col gap-1.5 rounded justify-center items-center py-2 px-3 hover:bg-gray-100"
|
||||||
|
>
|
||||||
|
<img class="size-8" :src="app.logo" />
|
||||||
|
<div class="text-sm" @click="app.onClick">
|
||||||
|
{{ app.title }}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { Popover, createResource } from 'frappe-ui'
|
||||||
|
import { LayoutGrid, ChevronRight } from 'lucide-vue-next';
|
||||||
|
|
||||||
|
const apps = createResource({
|
||||||
|
url: 'frappe.apps.get_apps',
|
||||||
|
cache: 'apps',
|
||||||
|
auto: true,
|
||||||
|
transform: (data) => {
|
||||||
|
let _apps = [
|
||||||
|
{
|
||||||
|
name: 'frappe',
|
||||||
|
logo: '/assets/lms/images/desk.png',
|
||||||
|
title: __('Desk'),
|
||||||
|
route: '/app',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
data.map((app) => {
|
||||||
|
if (app.name === 'lms') return
|
||||||
|
_apps.push({
|
||||||
|
name: app.name,
|
||||||
|
logo: app.logo,
|
||||||
|
title: __(app.title),
|
||||||
|
route: app.route,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return _apps
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -66,6 +66,7 @@
|
|||||||
import LMSLogo from '@/components/Icons/LMSLogo.vue'
|
import LMSLogo from '@/components/Icons/LMSLogo.vue'
|
||||||
import { sessionStore } from '@/stores/session'
|
import { sessionStore } from '@/stores/session'
|
||||||
import { Dropdown } from 'frappe-ui'
|
import { Dropdown } from 'frappe-ui'
|
||||||
|
import Apps from '@/components/Apps.vue'
|
||||||
import {
|
import {
|
||||||
ChevronDown,
|
ChevronDown,
|
||||||
LogIn,
|
LogIn,
|
||||||
@@ -77,7 +78,7 @@ import {
|
|||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { convertToTitleCase } from '../utils'
|
import { convertToTitleCase } from '../utils'
|
||||||
import { usersStore } from '@/stores/user'
|
import { usersStore } from '@/stores/user'
|
||||||
import { ref } from 'vue'
|
import { ref, markRaw } from 'vue'
|
||||||
import SettingsModal from '@/components/Modals/Settings.vue'
|
import SettingsModal from '@/components/Modals/Settings.vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -105,11 +106,7 @@ const userDropdownOptions = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: ArrowRightLeft,
|
component: markRaw(Apps),
|
||||||
label: 'Switch to Desk',
|
|
||||||
onClick: () => {
|
|
||||||
window.location.href = '/app'
|
|
||||||
},
|
|
||||||
condition: () => {
|
condition: () => {
|
||||||
let cookies = new URLSearchParams(document.cookie.split('; ').join('&'))
|
let cookies = new URLSearchParams(document.cookie.split('; ').join('&'))
|
||||||
let system_user = cookies.get('system_user')
|
let system_user = cookies.get('system_user')
|
||||||
|
|||||||
16
lms/hooks.py
16
lms/hooks.py
@@ -4,9 +4,11 @@ app_name = "frappe_lms"
|
|||||||
app_title = "Frappe LMS"
|
app_title = "Frappe LMS"
|
||||||
app_publisher = "Frappe"
|
app_publisher = "Frappe"
|
||||||
app_description = "Frappe LMS App"
|
app_description = "Frappe LMS App"
|
||||||
app_icon = "octicon octicon-file-directory"
|
app_icon_url = "/assets/lms/images/lms-logo.png"
|
||||||
|
app_icon_title = "Learning"
|
||||||
|
app_icon_route = "/lms"
|
||||||
app_color = "grey"
|
app_color = "grey"
|
||||||
app_email = "school@frappe.io"
|
app_email = "jannat@frappe.io"
|
||||||
app_license = "AGPL"
|
app_license = "AGPL"
|
||||||
|
|
||||||
# Includes in <head>
|
# Includes in <head>
|
||||||
@@ -61,8 +63,6 @@ web_include_js = ["website.bundle.js"]
|
|||||||
after_install = "lms.install.after_install"
|
after_install = "lms.install.after_install"
|
||||||
after_sync = "lms.install.after_sync"
|
after_sync = "lms.install.after_sync"
|
||||||
before_uninstall = "lms.install.before_uninstall"
|
before_uninstall = "lms.install.before_uninstall"
|
||||||
|
|
||||||
|
|
||||||
setup_wizard_requires = "assets/lms/js/setup_wizard.js"
|
setup_wizard_requires = "assets/lms/js/setup_wizard.js"
|
||||||
|
|
||||||
# Desk Notifications
|
# Desk Notifications
|
||||||
@@ -231,3 +231,11 @@ profile_url_prefix = "/users/"
|
|||||||
signup_form_template = "lms.plugins.show_custom_signup"
|
signup_form_template = "lms.plugins.show_custom_signup"
|
||||||
|
|
||||||
on_session_creation = "lms.overrides.user.on_session_creation"
|
on_session_creation = "lms.overrides.user.on_session_creation"
|
||||||
|
|
||||||
|
add_to_apps_screen = [{
|
||||||
|
"name": "lms",
|
||||||
|
"logo": "/assets/lms/images/lms-logo.png",
|
||||||
|
"title": "Learning",
|
||||||
|
"route": "/lms",
|
||||||
|
"has_permission": "lms.lms.api.check_app_permission"
|
||||||
|
}]
|
||||||
@@ -597,3 +597,15 @@ def get_members(start=0, search=""):
|
|||||||
member.role = "LMS Student"
|
member.role = "LMS Student"
|
||||||
|
|
||||||
return members
|
return members
|
||||||
|
|
||||||
|
def check_app_permission():
|
||||||
|
"""Check if the user has permission to access the app."""
|
||||||
|
if frappe.session.user == "Administrator":
|
||||||
|
return True
|
||||||
|
|
||||||
|
roles = frappe.get_roles()
|
||||||
|
lms_roles = ["Moderator", "Course Creator", "Batch Evaluator", "LMS Student"]
|
||||||
|
if any(role in roles for role in lms_roles):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|||||||
BIN
lms/public/images/desk.png
Normal file
BIN
lms/public/images/desk.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Reference in New Issue
Block a user