Skip to content

Commit

Permalink
feat: New Knowledge Base for Customer Portal
Browse files Browse the repository at this point in the history
  • Loading branch information
RitvikSardana committed Sep 30, 2024
1 parent 3c5b83c commit c847199
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 58 deletions.
6 changes: 4 additions & 2 deletions desk/src/components/SidebarLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
'w-full': isExpanded,
'w-8': !isExpanded,
'shadow-sm': isActive,
'bg-white': isActive,
[bgColor]: isActive,
'hover:bg-gray-100': !isActive,
}"
@click="handle"
Expand Down Expand Up @@ -40,16 +40,18 @@ import { Icon } from "@iconify/vue";
interface P {
icon: unknown;
label: string;
isExpanded: boolean;
isExpanded?: boolean;
isActive?: boolean;
onClick?: () => void;
to?: string;
bgColor?: string;
}
const props = withDefaults(defineProps<P>(), {
isActive: false,
onClick: () => () => true,
to: "",
bgColor: "bg-white",
});
const router = useRouter();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<template>
<div class="flex flex-col p-5 px-10">
<h3 class="text-xl font-semibold text-gray-800">
{{ categoryName }}
</h3>
</div>
</template>

<script setup lang="ts">
import { createListResource, createResource } from "frappe-ui";
import { ref } from "vue";
import { watch } from "vue";
const props = defineProps<{
categoryId: string;
}>();
const categoryName = ref("");
const categoryResource = createResource({
url: "helpdesk.api.kbase.get_category",
name: props.categoryId,
cache: ["category", props.categoryId],
params: {
category: props.categoryId,
},
onSuccess: (data) => {
categoryName.value = data.category_name ?? data.name;
},
auto: true,
});
const subCategories = createListResource({
doctype: "HD Article Category",
name: props.categoryId,
cache: ["category", props.categoryId],
fields: ["name", "category_name", "icon", "parent_category"],
filters: {
parent_category: props.categoryId,
},
auto: true,
});
watch(
() => props.categoryId,
() => {
categoryResource.update({
params: {
category: props.categoryId,
},
});
subCategories.update({
params: { name: props.categoryId },
});
categoryResource.reload();
subCategories.reload();
}
);
</script>

<style scoped></style>
60 changes: 60 additions & 0 deletions desk/src/components/knowledge-base-v2/KnowledgeBaseSidebar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<template>
<div
class="h-full space-y-2 border-r px-3.5 py-2.5"
:style="{
'min-width': '242px',
'max-width': '242px',
}"
>
<div class="flex flex-col gap-1">
<div class="text-sm font-medium text-gray-600">Categories</div>
<div v-if="!categories.isLoading" class="flex flex-col gap-1">
<!-- all categories here -->
<SidebarLink
v-for="category in categories.data"
:key="category.label"
:icon="getIcon(category.icon, true)"
:is-active="activeCategory === category.name"
:is-expanded="true"
:label="category.category_name"
:bg-color="'bg-gray-100'"
@click="handleClick(category.name)"
/>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import SidebarLink from "../SidebarLink.vue";
import { createListResource } from "frappe-ui";
import { getIcon } from "@/pages/knowledge-base/util";
const emit = defineEmits(["category-change"]);
const activeCategory = defineModel();
const categories = createListResource({
doctype: "HD Article Category",
auto: true,
fields: ["name", "category_name", "icon", "parent_category"],
filters: {
parent_category: "",
},
transform: (data) => {
const firstCategory = {
name: "Explore All Articles",
category_name: "Explore All Articles",
icon: "search",
};
return [firstCategory, ...data];
},
});
function handleClick(name: string) {
if (activeCategory.value === name) return;
activeCategory.value = name;
}
</script>

<style scoped></style>
8 changes: 3 additions & 5 deletions desk/src/components/layouts/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,10 @@ const notificationStore = useNotificationStore();
const { isExpanded, width } = storeToRefs(useSidebarStore());
const device = useDevice();
const showSettingsModal = ref(false);
const isCustomerPortal = computed(() =>
CUSTOMER_PORTAL_ROUTES.includes(route.name)
);
const isCustomerPortal = route.meta.public ?? false;
const menuOptions = computed(() => {
return isCustomerPortal.value
return isCustomerPortal
? customerPortalSidebarOptions
: agentPortalSidebarOptions;
});
Expand Down Expand Up @@ -149,7 +147,7 @@ const agentPortalDropdown = computed(() => [
]);
const profileSettings = computed(() => {
return isCustomerPortal.value
return isCustomerPortal
? customerPortalDropdown.value
: agentPortalDropdown.value;
});
Expand Down
2 changes: 1 addition & 1 deletion desk/src/components/layouts/layoutSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ export const customerPortalSidebarOptions = [
{
label: "Knowledge base",
icon: LucideBookOpen,
to: "KBHome",
to: "KnowledgeBasePublicNew",
},
];
27 changes: 27 additions & 0 deletions desk/src/pages/knowledge-base-v2/KnowledgeBasePublic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<div class="flex flex-col">
<LayoutHeader>
<template #left-header>
<div class="text-lg font-medium text-gray-900">Knowledge base</div>
</template>
</LayoutHeader>
<div class="flex grow">
<KnowledgeBaseSidebar v-model="currentCategory" />
<KnowledgeBaseCategoryHandler
v-if="currentCategory !== 'Explore All Articles'"
:category-id="currentCategory"
/>
<div v-else>All</div>
</div>
</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { LayoutHeader } from "@/components";
import KnowledgeBaseSidebar from "@/components/knowledge-base-v2/KnowledgeBaseSidebar.vue";
import KnowledgeBaseCategoryHandler from "@/components/knowledge-base-v2/KnowledgeBaseCategoryHandler.vue";
const currentCategory = ref("Explore All Articles");
</script>

<style scoped></style>
73 changes: 23 additions & 50 deletions desk/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,32 +54,7 @@ const routes = [
path: "",
component: () => import("@/pages/HRoot.vue"),
},
{
path: "/knowledge-base",
component: () => import("@/pages/KnowledgeBasePublic.vue"),
children: [
{
path: "",
name: "KBHome",
component: () => import("@/pages/KnowledgeBasePublicHome.vue"),
},
{
path: ":categoryId",
name: "KBCategoryPublic",
component: () => import("@/pages/KnowledgeBasePublicCategory.vue"),
props: true,
},
{
path: "articles/:articleId",
name: "KBArticlePublic",
component: () => import("@/pages/KnowledgeBaseArticle.vue"),
meta: {
public: true,
},
props: true,
},
],
},
// Customer portal routing
{
path: "",
name: "CustomerRoot",
Expand All @@ -93,17 +68,11 @@ const routes = [
// handle tickets routing
{
path: "my-tickets",
meta: {
auth: true,
},
children: [
{
path: "",
name: "TicketsCustomer",
component: () => import("@/pages/Tickets.vue"),
meta: {
public: true,
},
},
{
path: "new/:templateId?",
Expand All @@ -113,38 +82,31 @@ const routes = [
meta: {
onSuccessRoute: "TicketCustomer",
parent: "TicketsCustomer",
public: true,
},
},
{
path: ":ticketId",
name: "TicketCustomer",
component: () => import("@/pages/TicketCustomer.vue"),
props: true,
meta: {
public: true,
},
},
],
},
// handle knowledge base routing
{
path: "kb-new",
meta: {
auth: true,
},
path: "knowledge-base-public",
children: [
{
path: "",
name: "KnowledgeBasePublicNew",
component: () =>
import("@/pages/knowledge-base-v2/KnowledgeBasePublic.vue"),
},
],
},
],
},
{
path: "/onboarding",
name: ONBOARDING_PAGE,
component: () => import("@/pages/onboarding/SimpleOnboarding.vue"),
},
{
path: "/:invalidpath",
name: "Invalid Page",
component: () => import("@/pages/InvalidPage.vue"),
},
// Agent Portal Routing
{
path: "",
name: "AgentRoot",
Expand Down Expand Up @@ -248,6 +210,17 @@ const routes = [
},
],
},
// Additonal routes
{
path: "/onboarding",
name: ONBOARDING_PAGE,
component: () => import("@/pages/onboarding/SimpleOnboarding.vue"),
},
{
path: "/:invalidpath",
name: "Invalid Page",
component: () => import("@/pages/InvalidPage.vue"),
},
];

const handleMobileView = (componentName) => {
Expand Down
7 changes: 7 additions & 0 deletions helpdesk/api/kbase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import frappe


@frappe.whitelist()
def get_category(category):
category_doc = frappe.get_doc("HD Article Category", category)
return category_doc

0 comments on commit c847199

Please sign in to comment.