chore: resolved conflicts
This commit is contained in:
@@ -93,11 +93,19 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { createResource, TextEditor, Button, Dropdown, toast } from 'frappe-ui'
|
||||
import {
|
||||
call,
|
||||
createResource,
|
||||
TextEditor,
|
||||
Button,
|
||||
Dropdown,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { timeAgo } from '@/utils'
|
||||
import UserAvatar from '@/components/UserAvatar.vue'
|
||||
import { ChevronLeft, MoreHorizontal } from 'lucide-vue-next'
|
||||
import { ref, inject, onMounted, onUnmounted } from 'vue'
|
||||
import { useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
const showTopics = defineModel('showTopics')
|
||||
const newReply = ref('')
|
||||
@@ -107,6 +115,7 @@ const allUsers = inject('$allUsers')
|
||||
const mentionUsers = ref([])
|
||||
const renderEditor = ref(false)
|
||||
const readOnlyMode = window.read_only_mode
|
||||
const { capture } = useTelemetry()
|
||||
|
||||
const props = defineProps({
|
||||
topic: {
|
||||
@@ -143,19 +152,6 @@ const replies = createResource({
|
||||
auto: true,
|
||||
})
|
||||
|
||||
const newReplyResource = createResource({
|
||||
url: 'frappe.client.insert',
|
||||
makeParams(values) {
|
||||
return {
|
||||
doc: {
|
||||
doctype: 'Discussion Reply',
|
||||
reply: newReply.value,
|
||||
topic: props.topic.name,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const fetchMentionUsers = () => {
|
||||
if (user.data?.is_student) {
|
||||
renderEditor.value = true
|
||||
@@ -178,78 +174,61 @@ const fetchMentionUsers = () => {
|
||||
}
|
||||
|
||||
const postReply = () => {
|
||||
newReplyResource.submit(
|
||||
{},
|
||||
{
|
||||
validate() {
|
||||
if (!newReply.value) {
|
||||
return 'Reply cannot be empty'
|
||||
}
|
||||
},
|
||||
onSuccess() {
|
||||
newReply.value = ''
|
||||
replies.reload()
|
||||
},
|
||||
onError(err) {
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const editReplyResource = createResource({
|
||||
url: 'frappe.client.set_value',
|
||||
makeParams(values) {
|
||||
return {
|
||||
if (!newReply.value) {
|
||||
toast.error(__('Reply cannot be empty.'))
|
||||
return
|
||||
}
|
||||
call('frappe.client.insert', {
|
||||
doc: {
|
||||
doctype: 'Discussion Reply',
|
||||
name: values.name,
|
||||
fieldname: 'reply',
|
||||
value: values.reply,
|
||||
}
|
||||
},
|
||||
})
|
||||
reply: newReply.value,
|
||||
topic: props.topic.name,
|
||||
},
|
||||
})
|
||||
.then((data) => {
|
||||
newReply.value = ''
|
||||
replies.reload()
|
||||
capture('discussion_reply_created')
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.messages?.[0] || err)
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
|
||||
const postEdited = (reply) => {
|
||||
editReplyResource.submit(
|
||||
{
|
||||
name: reply.name,
|
||||
reply: reply.reply,
|
||||
},
|
||||
{
|
||||
validate() {
|
||||
if (!reply.reply) {
|
||||
return 'Reply cannot be empty'
|
||||
}
|
||||
},
|
||||
onSuccess() {
|
||||
reply.editable = false
|
||||
replies.reload()
|
||||
},
|
||||
}
|
||||
)
|
||||
if (!reply.reply) {
|
||||
toast.error(__('Reply cannot be empty.'))
|
||||
return
|
||||
}
|
||||
call('frappe.client.set_value', {
|
||||
doctype: 'Discussion Reply',
|
||||
name: reply.name,
|
||||
fieldname: 'reply',
|
||||
value: reply.reply,
|
||||
})
|
||||
.then(() => {
|
||||
reply.editable = false
|
||||
replies.reload()
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.messages?.[0] || err)
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
|
||||
const deleteReplyResource = createResource({
|
||||
url: 'frappe.client.delete',
|
||||
makeParams(values) {
|
||||
return {
|
||||
doctype: 'Discussion Reply',
|
||||
name: values.name,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const deleteReply = (reply) => {
|
||||
deleteReplyResource.submit(
|
||||
{
|
||||
name: reply.name,
|
||||
},
|
||||
{
|
||||
onSuccess() {
|
||||
replies.reload()
|
||||
},
|
||||
}
|
||||
)
|
||||
call('frappe.client.delete', {
|
||||
doctype: 'Discussion Reply',
|
||||
name: reply.name,
|
||||
})
|
||||
.then(() => {
|
||||
replies.reload()
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.messages?.[0] || err)
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
|
||||
@@ -34,17 +34,13 @@
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import {
|
||||
Dialog,
|
||||
FormControl,
|
||||
TextEditor,
|
||||
createResource,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { call, Dialog, FormControl, TextEditor, toast } from 'frappe-ui'
|
||||
import { reactive } from 'vue'
|
||||
import { singularize } from '@/utils'
|
||||
import { useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
const topics = defineModel('reloadTopics')
|
||||
const { capture } = useTelemetry()
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
@@ -66,64 +62,50 @@ const topic = reactive({
|
||||
reply: '',
|
||||
})
|
||||
|
||||
const topicResource = createResource({
|
||||
url: 'frappe.client.insert',
|
||||
makeParams(values) {
|
||||
return {
|
||||
doc: {
|
||||
doctype: 'Discussion Topic',
|
||||
reference_doctype: props.doctype,
|
||||
reference_docname: props.docname,
|
||||
title: topic.title,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const replyResource = createResource({
|
||||
url: 'frappe.client.insert',
|
||||
makeParams(values) {
|
||||
return {
|
||||
doc: {
|
||||
doctype: 'Discussion Reply',
|
||||
topic: values.topic,
|
||||
reply: topic.reply,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const submitTopic = (close) => {
|
||||
topicResource.submit(
|
||||
{},
|
||||
{
|
||||
validate() {
|
||||
if (!topic.title) {
|
||||
return 'Title cannot be empty.'
|
||||
}
|
||||
if (!topic.reply) {
|
||||
return 'Reply cannot be empty.'
|
||||
}
|
||||
},
|
||||
onSuccess(data) {
|
||||
replyResource.submit(
|
||||
{
|
||||
topic: data.name,
|
||||
},
|
||||
{
|
||||
onSuccess() {
|
||||
topic.title = ''
|
||||
topic.reply = ''
|
||||
topics.value.reload()
|
||||
close()
|
||||
},
|
||||
}
|
||||
)
|
||||
},
|
||||
onError(err) {
|
||||
toast.error(err.messages?.[0] || err)
|
||||
},
|
||||
}
|
||||
)
|
||||
if (!topic.title) {
|
||||
toast.error(__('Title cannot be empty.'))
|
||||
return
|
||||
}
|
||||
if (!topic.reply) {
|
||||
toast.error(__('Details cannot be empty.'))
|
||||
return
|
||||
}
|
||||
call('frappe.client.insert', {
|
||||
doc: {
|
||||
doctype: 'Discussion Topic',
|
||||
reference_doctype: props.doctype,
|
||||
reference_docname: props.docname,
|
||||
title: topic.title,
|
||||
},
|
||||
})
|
||||
.then((data) => {
|
||||
createReply(data.name, close)
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.messages?.[0] || err)
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
|
||||
const createReply = (topicName, close) => {
|
||||
call('frappe.client.insert', {
|
||||
doc: {
|
||||
doctype: 'Discussion Reply',
|
||||
topic: topicName,
|
||||
reply: topic.reply,
|
||||
},
|
||||
})
|
||||
.then((data) => {
|
||||
topic.title = ''
|
||||
topic.reply = ''
|
||||
topics.value.reload()
|
||||
capture('discussion_topic_created')
|
||||
close()
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.messages?.[0] || err)
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -131,6 +131,7 @@ import { ref, watch, reactive, inject } from 'vue'
|
||||
import { RefreshCw, Plus, Search, Shield } from 'lucide-vue-next'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
import type { User } from '@/components/Settings/types'
|
||||
import { useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
type Member = {
|
||||
username: string
|
||||
@@ -149,6 +150,7 @@ const hasNextPage = ref(false)
|
||||
const showForm = ref(false)
|
||||
const user = inject<User | null>('$user')
|
||||
const { updateOnboardingStep } = useOnboarding('learning')
|
||||
const { capture } = useTelemetry()
|
||||
|
||||
const member = reactive({
|
||||
email: '',
|
||||
@@ -202,6 +204,7 @@ const addMember = (close: () => void) => {
|
||||
})
|
||||
.then((data: Member) => {
|
||||
if (user?.data?.is_system_manager) updateOnboardingStep('invite_students')
|
||||
capture('user_added')
|
||||
show.value = false
|
||||
router.push({
|
||||
name: 'ProfileRoles',
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Button, Dialog, FormControl, TextEditor, toast } from 'frappe-ui'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
import { ref, inject, onMounted, onBeforeUnmount, watch } from 'vue'
|
||||
import { ref, inject, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { cleanError, openSettings } from '@/utils'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
@@ -188,13 +188,13 @@ const keyboardShortcut = (e: KeyboardEvent) => {
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('keydown', keyboardShortcut)
|
||||
capture('batch_form_opened')
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('keydown', keyboardShortcut)
|
||||
})
|
||||
|
||||
watch(show, () => {
|
||||
if (show.value) capture('batch_form_opened')
|
||||
capture('batch_form_closed', {
|
||||
data: batch.value,
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Button, Dialog, FormControl, TextEditor, toast } from 'frappe-ui'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
import { inject, onMounted, onBeforeUnmount, ref, watch } from 'vue'
|
||||
import { inject, onMounted, onBeforeUnmount, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { cleanError, openSettings } from '@/utils'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
@@ -148,13 +148,13 @@ const keyboardShortcut = (e: KeyboardEvent) => {
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('keydown', keyboardShortcut)
|
||||
capture('course_form_opened')
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('keydown', keyboardShortcut)
|
||||
})
|
||||
|
||||
watch(show, () => {
|
||||
if (show.value) capture('course_form_opened')
|
||||
capture('course_form_closed', {
|
||||
data: course.value,
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
<template>
|
||||
<!-- <header
|
||||
class="sticky flex items-center justify-between top-0 z-10 border-b bg-surface-white px-3 py-2.5 sm:px-5"
|
||||
>
|
||||
<Breadcrumbs :items="[{ label: __('Home'), route: { name: 'Home' } }]" />
|
||||
</header> -->
|
||||
<div class="w-full px-5 pt-5 pb-10">
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center justify-between">
|
||||
@@ -11,9 +6,8 @@
|
||||
{{ __('Hey') }}, {{ user.data?.full_name }} 👋
|
||||
</div>
|
||||
<div>
|
||||
<TabButtons v-if="isAdmin" v-model="currentTab" :buttons="tabs" />
|
||||
<div
|
||||
v-else
|
||||
v-if="!isAdmin"
|
||||
@click="showStreakModal = true"
|
||||
class="bg-surface-amber-2 px-2 py-1 rounded-md cursor-pointer"
|
||||
>
|
||||
@@ -35,19 +29,16 @@
|
||||
:liveClasses="adminLiveClasses"
|
||||
:evals="adminEvals"
|
||||
/>
|
||||
<StudentHome v-else :myLiveClasses="myLiveClasses" />
|
||||
<StudentHome
|
||||
v-else-if="currentTab === 'student'"
|
||||
:myLiveClasses="myLiveClasses"
|
||||
/>
|
||||
</div>
|
||||
<Streak v-model="showStreakModal" :streakInfo="streakInfo" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, inject, onMounted, ref } from 'vue'
|
||||
import {
|
||||
Breadcrumbs,
|
||||
call,
|
||||
createResource,
|
||||
TabButtons,
|
||||
usePageMeta,
|
||||
} from 'frappe-ui'
|
||||
import { call, createResource, usePageMeta } from 'frappe-ui'
|
||||
import { sessionStore } from '@/stores/session'
|
||||
import StudentHome from '@/pages/Home/StudentHome.vue'
|
||||
import AdminHome from '@/pages/Home/AdminHome.vue'
|
||||
@@ -56,10 +47,10 @@ import Streak from '@/pages/Home/Streak.vue'
|
||||
const user = inject<any>('$user')
|
||||
const { brand } = sessionStore()
|
||||
const evalCount = ref(0)
|
||||
const currentTab = ref<'student' | 'instructor'>('instructor')
|
||||
const currentTab = ref<'student' | 'instructor'>('student')
|
||||
const showStreakModal = ref(false)
|
||||
|
||||
onMounted(() => {
|
||||
const fetchEvalCount = () => {
|
||||
call('frappe.client.get_count', {
|
||||
doctype: 'LMS Certificate Request',
|
||||
filters: {
|
||||
@@ -70,7 +61,7 @@ onMounted(() => {
|
||||
}).then((data: any) => {
|
||||
evalCount.value = data
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const isAdmin = computed(() => {
|
||||
return (
|
||||
@@ -80,6 +71,15 @@ const isAdmin = computed(() => {
|
||||
)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (isAdmin.value) {
|
||||
currentTab.value = 'instructor'
|
||||
} else {
|
||||
currentTab.value = 'student'
|
||||
fetchEvalCount()
|
||||
}
|
||||
})
|
||||
|
||||
const myLiveClasses = createResource({
|
||||
url: 'lms.lms.api.get_my_live_classes',
|
||||
auto: !isAdmin.value ? true : false,
|
||||
@@ -151,11 +151,6 @@ const subtitle = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const tabs = [
|
||||
{ label: __('Student'), value: 'student' },
|
||||
{ label: __('Instructor'), value: 'instructor' },
|
||||
]
|
||||
|
||||
usePageMeta(() => {
|
||||
return {
|
||||
title: __('Home'),
|
||||
|
||||
@@ -783,11 +783,11 @@ const isAdmin = computed(() => {
|
||||
|
||||
const allowEdit = () => {
|
||||
if (window.read_only_mode) return false
|
||||
if (isAdmin.value) return true
|
||||
return false
|
||||
return isAdmin.value
|
||||
}
|
||||
|
||||
const allowInstructorContent = () => {
|
||||
if (window.read_only_mode) return false
|
||||
return isAdmin.value
|
||||
}
|
||||
|
||||
|
||||
@@ -236,10 +236,10 @@ export function getEditorTools() {
|
||||
html: "<iframe style='width: 100%; height: 30rem; border: 1px solid #D3D3D3; border-radius: 12px; margin: 1rem 0;' frameborder='0' allowfullscreen='true'></iframe>",
|
||||
},
|
||||
codesandbox: {
|
||||
regex: /^https:\/\/codesandbox\.io\/(?:embed\/)?([A-Za-z0-9_-]+)(?:\?[^\/]*)?$/,
|
||||
regex: /^https:\/\/codesandbox\.io\/(?:(?:p\/(?:sandbox|devbox)\/)|(?:embed\/)|(?:s\/))?([A-Za-z0-9_-]+)(?:[\/\?].*)?$/,
|
||||
embedUrl:
|
||||
'https://codesandbox.io/embed/<%= remote_id %>?view=editor+%2B+preview&module=%2Findex.html',
|
||||
html: "<iframe style='width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden;' sandbox='allow-mods allow-forms allow-popups allow-scripts allow-same-origin' frameborder='0' allowfullscreen='true'></iframe>",
|
||||
html: "<iframe style='width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden;' sandbox='allow-modals allow-forms allow-popups allow-scripts allow-same-origin' frameborder='0' allowfullscreen='true'></iframe>",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user