Skip to content

Commit

Permalink
Merge pull request #2108 from frappe/develop
Browse files Browse the repository at this point in the history
chore(release): dev to main
  • Loading branch information
RitvikSardana authored Dec 19, 2024
2 parents 4a1ba86 + 0db7083 commit 3a29875
Show file tree
Hide file tree
Showing 23 changed files with 206 additions and 50 deletions.
Binary file added .github/AgentListView.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/Hero2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/KB.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/Search2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 55 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
<div align="center" markdown="1">

<img src=".github/hd-logo.svg" alt="Frappe Helpdesk logo" width="100"/>
<img src=".github/hd-logo.svg" alt="Frappe Helpdesk logo" width="80"/>
<h1>Frappe Helpdesk</h1>

**Customer Service, Made Simple and Effective**

![GitHub release (latest by date)](https://img.shields.io/github/v/release/frappe/helpdesk)
[![codecov](https://codecov.io/github/frappe/helpdesk/branch/develop/graph/badge.svg?token=8ZXHCY4G9U)](https://codecov.io/github/frappe/helpdesk)


</div>


<div align="center">
<img src="./screenshot.webp" alt="Hero Image" width="72%" />
<img src="./.github/Hero2.png" alt="Hero Image" width="100%" />
</div>
<br />
<div align="center">
Expand All @@ -26,30 +27,62 @@ Frappe Helpdesk is an 100% open-source Ticket Management tool which helps you s



## Motivation
### Motivation
Managing issues from our customers was a big challenge for us. We were using the ERPNext support module which was not very good in UI and the UX was also not good. We wanted to have a tool that can be easily integrated with our existing system and can be customized as per our needs. So we decided to build Frappe Helpdesk.

## Key Features
### Key Features

- **Agent and Customer Portal Views**: Dual portals for agents and customers to simplify issue submission and management.

- **Customizable SLAs**: Discover how you can set and track SLAs for better response times.

- **Assignment Rules**: Custom auto-assignment of tickets based on priority, issue type, or workload.

- **Email Account Setup**: Set up email accounts to automatically create tickets from incoming emails. Choose from various Mail providers like Frappe Mail, Gmail, Outlook, Sendgrid, Sparkpost, Yahoo, Yandex, etc.
- **Knowledge Base**: Learn how to create and manage help articles to empower users and reduce tickets.

- **Canned Responses**: Pre-written replies for common queries to ensure quick and consistent communication.

- **Knowledge Base**: Learn how to create and manage help articles to empower users and reduce tickets.
<details open>
<summary >View Screenshots</summary>
<h3></h3>

<div align="center">
<sub>
Agent List View
</sub>
</div>

![Agent List View](.github/AgentListView.png)


<div align="center">
<sub>
Upload articles and let your customer solve there queries through the Knowledge Base.
</sub>
</div>

![Knowledge Base](.github/KB.png)

<div align="center">
<sub>
With advanced search, your customers will be recommended relevant articles regarding their issue.
</sub>
</div>

## Under the Hood

- [**Frappe Framework**](https://github.com/frappe/frappe): A full-stack web application framework written in Python and Javascript. The framework provides a robust foundation for building web applications, including a database abstraction layer, user authentication, and a REST API.
![Article Search](.github/Search2.png)

- [**Frappe UI**](https://github.com/frappe/frappe-ui): A Vue-based UI library, to provide a modern user interface. The Frappe UI library provides a variety of components that can be used to build single-page applications on top of the Frappe Framework.


</details>
<br>


### Under the Hood

- [**Frappe Framework**](https://github.com/frappe/frappe): A full-stack web application framework written in Python and Javascript.

- [**Frappe UI**](https://github.com/frappe/frappe-ui): A Vue-based UI library, to provide a modern user interface.


## Production Setup
Expand Down Expand Up @@ -134,15 +167,26 @@ To setup the repository locally follow the steps mentioned below:
1. Run `bench --site helpdesk.test install-app helpdesk`.
1. Now open the URL `http://helpdesk.test:8000/helpdesk` in your browser, you should see the app running


**For Frontend Development**
1. Open a new terminal session and cd into `frappe-bench/apps/helpdesk/desk`, and run the following commands:
```
yarn install
yarn dev or yarn dev --host helpdesk.test
```
1. Now, you can access the site on vite dev server at `http://helpdesk.test:8080`
**Note:** You'll find all the code related to Helpdesk's frontend inside `frappe-bench/apps/helpdesk/desk`
## Learn and connect
- [Telegram Public Group](https://t.me/frappedesk)
- [Discuss Forum](https://discuss.frappe.io/c/frappehelpdesk/69)
- [Documentation](https://docs.frappe.io/helpdesk)
<h2></h2>
<br>
<div align="center" style="padding-top: 0.75rem;">
<br>
<div align="center">
<a href="https://frappe.io" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://frappe.io/files/Frappe-white.png">
Expand Down
2 changes: 1 addition & 1 deletion desk/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<RouterView class="antialiased" :key="$route.fullPath" />
<RouterView class="antialiased" />
<Toasts />
<KeymapDialog />
<Dialogs />
Expand Down
14 changes: 7 additions & 7 deletions desk/src/components/SidebarLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[bgColor]: isActive,
[hvColor]: !isActive,
}"
@click="handle"
@click="handleNavigation"
>
<span
class="shrink-0 text-gray-700"
Expand Down Expand Up @@ -57,12 +57,12 @@ const props = withDefaults(defineProps<P>(), {
});
const router = useRouter();
function handle() {
function handleNavigation() {
props.onClick();
if (props.to) {
router.push({
name: props.to,
});
}
if (!props.to) return;
if (props.to === router.currentRoute.value.name) return;
router.push({
name: props.to,
});
}
</script>
26 changes: 20 additions & 6 deletions desk/src/components/UniInput2.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,26 @@
>
<component
:is="component"
:key="transValue"
:key="field.fieldname"
class="form-control"
:placeholder="`Add ${field.label}`"
:value="transValue"
@change="
emitUpdate(field.fieldname, $event.value || $event.target.value)
v-on="
textFields.includes(field.fieldtype)
? {
blur: (event) =>
emitUpdate(
field.fieldname,
event.value || event.target.value
),
}
: {
change: (event) =>
emitUpdate(
field.fieldname,
event.value || event.target.value
),
}
"
/>
</div>
Expand Down Expand Up @@ -47,6 +61,8 @@ interface E {
const props = defineProps<P>();
const emit = defineEmits<E>();
const textFields = ["Long Text", "Small Text", "Text"];
const component = computed(() => {
if (props.field.url_method) {
return h(Autocomplete, {
Expand Down Expand Up @@ -75,9 +91,7 @@ const component = computed(() => {
},
],
});
} else if (
["Long Text", "Small Text", "Text"].includes(props.field.fieldtype)
) {
} else if (textFields.includes(props.field.fieldtype)) {
return h(FormControl, {
type: "textarea",
});
Expand Down
2 changes: 1 addition & 1 deletion desk/src/components/ticket/TicketsListView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
</ListRowItem>
</ListRow>
</ListRows>
<ListSelectBanner v-if="!isCustomerPortal">
<ListSelectBanner>
<template #actions="{ selections }">
<Dropdown
:options="[
Expand Down
2 changes: 1 addition & 1 deletion desk/src/components/ticket/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { default as TicketAgentActivities } from "./TicketAgentActivities.vue";
export { default as TicketAgentSidebar } from "./TicketAgentSidebar.vue";
export { default as TicketsAgentList } from "./TicketsListView.vue";
export { default as TicketsListView } from "./TicketsListView.vue";
17 changes: 13 additions & 4 deletions desk/src/pages/TicketAgent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,12 @@ const props = defineProps({
required: true,
},
});
watch(
() => props.ticketId,
() => {
ticket.reload();
}
);
provide("communicationArea", communicationAreaRef);
let storage = useStorage("ticket_agent", {
Expand All @@ -184,9 +189,9 @@ const ticket = createResource({
url: "helpdesk.helpdesk.doctype.hd_ticket.api.get_one",
cache: ["Ticket", props.ticketId],
auto: true,
params: {
makeParams: () => ({
name: props.ticketId,
},
}),
transform: (data) => {
if (data._assign) {
data.assignees = JSON.parse(data._assign).map((assignee) => {
Expand All @@ -202,9 +207,14 @@ const ticket = createResource({
onSuccess: (data) => {
setupCustomActions(data, {
doc: data,
updateField,
});
},
});
function updateField(name, value, callback = () => {}) {
updateTicket(name, value);
callback();
}
const breadcrumbs = computed(() => {
let items = [{ label: "Tickets", route: { name: "TicketsAgent" } }];
Expand Down Expand Up @@ -356,7 +366,6 @@ function updateTicket(fieldname: string, value: string) {
auto: true,
onSuccess: () => {
isLoading.value = false;
ticket.reload();
createToast({
title: "Ticket updated",
icon: "check",
Expand Down
50 changes: 50 additions & 0 deletions desk/src/pages/TicketCustomer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
<Breadcrumbs :items="breadcrumbs" />
</template>
<template #right-header>
<CustomActions
v-if="ticket.data._customActions"
:actions="ticket.data._customActions"
/>
<Button
v-if="ticket.data.status !== 'Closed'"
label="Close"
Expand Down Expand Up @@ -73,6 +77,7 @@ import TicketCustomerSidebar from "@/components/ticket/TicketCustomerSidebar.vue
import { useScreenSize } from "@/composables/screen";
import { useConfigStore } from "@/stores/config";
import { confirmDialog } from "frappe-ui";
import { setupCustomActions } from "@/utils";
interface P {
ticketId: string;
}
Expand All @@ -85,6 +90,7 @@ const ticket = createResource({
auto: true,
params: {
name: props.ticketId,
is_customer_portal: true,
},
onError: () => {
createToast({
Expand All @@ -94,6 +100,12 @@ const ticket = createResource({
});
router.replace("/my-tickets");
},
onSuccess: (data) => {
setupCustomActions(data, {
doc: data,
updateField,
});
},
});
provide(ITicket, ticket);
const editor = ref(null);
Expand Down Expand Up @@ -125,6 +137,44 @@ const send = createResource({
},
});
function updateField(name, value, callback = () => {}) {
updateTicket(name, value);
callback();
}
function updateTicket(fieldname: string, value: string) {
createResource({
url: "frappe.client.set_value",
params: {
doctype: "HD Ticket",
name: props.ticketId,
fieldname,
value,
},
auto: true,
onSuccess: () => {
ticket.reload();
createToast({
title: "Ticket updated",
icon: "check",
iconClasses: "text-green-600",
});
},
onError: (e) => {
const title =
e.messages && e.messages.length > 0
? e.messages[0]
: "Failed to update ticket";
createToast({
title,
icon: "x",
iconClasses: "text-red-600",
});
},
});
}
function handleClose() {
if (showFeedback.value) {
showFeedbackDialog.value = true;
Expand Down
4 changes: 2 additions & 2 deletions desk/src/pages/Tickets.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
@event:column="processColumns"
@event:reload="apply()"
/>
<TicketsAgentList
<TicketsListView
:rows="tickets?.data?.data || []"
:columns="columns"
:page-length="pageLength"
Expand All @@ -53,7 +53,7 @@
import { ref, computed, onMounted, onUnmounted } from "vue";
import { useStorage } from "@vueuse/core";
import { createResource, Breadcrumbs, usePageMeta } from "frappe-ui";
import { TicketsAgentList } from "@/components/ticket";
import { TicketsListView } from "@/components/ticket";
import { ViewControls, LayoutHeader } from "@/components";
import { useUserStore } from "@/stores/user";
import { useRoute } from "vue-router";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</div>
</div>
<div class="border-b pb-3">
<div class="text-3xl font-semibold text-gray-900">
<div class="text-2xl font-semibold text-gray-900">
{{ title }}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</div>
</div>
<div class="border-b pb-3">
<div class="text-3xl font-semibold text-gray-900">
<div class="text-2xl font-semibold text-gray-900">
{{ title }}
</div>
</div>
Expand Down
Loading

0 comments on commit 3a29875

Please sign in to comment.