Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ux): response editor #1220

Merged
merged 8 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix(ux): ticket single
  • Loading branch information
ssiyad committed May 24, 2023
commit b33fa8faedaed6b70d58010c186fc7250beeeb22
3 changes: 2 additions & 1 deletion desk/src/pages/desk/ticket/CommunicationItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
import { toRefs } from "vue";
import dayjs from "dayjs";
import { Avatar, Dropdown, FeatherIcon } from "frappe-ui";
import { editor } from "./data";
import { useTicketStore } from "./data";
import IconDot from "~icons/ph/dot-bold";
import AttachmentItem from "@/components/AttachmentItem.vue";

Expand Down Expand Up @@ -93,6 +93,7 @@ const props = defineProps({
});

const { content, date, sender, senderImage, cc, bcc } = toRefs(props);
const { editor } = useTicketStore();
const dateDisplay = dayjs(date.value).format("h:mm A");
const options = [
{
Expand Down
6 changes: 4 additions & 2 deletions desk/src/pages/desk/ticket/ContactDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Button
appearance="minimal"
icon="x"
@click="sidebar.isVisible = false"
@click="sidebar.isExpanded = false"
/>
</div>
<div class="flex items-center gap-3 border-b py-6">
Expand Down Expand Up @@ -51,11 +51,13 @@
import { isEmpty } from "lodash";
import { computed } from "vue";
import { Avatar, Button, createDocumentResource } from "frappe-ui";
import { sidebar, ticket } from "./data";
import { useTicketStore } from "./data";
import CustomFieldList from "./CustomFieldList.vue";
import OpenTicketList from "./OpenTicketList.vue";
import IconEmail from "~icons/espresso/email";

const { sidebar, ticket } = useTicketStore();

const c = createDocumentResource({
doctype: "Contact",
name: ticket.doc.contact,
Expand Down
4 changes: 3 additions & 1 deletion desk/src/pages/desk/ticket/ConversationBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ import { useScroll } from "@vueuse/core";
import dayjs from "dayjs";
import { orderBy, unionBy } from "lodash";
import { socket } from "@/socket";
import { ticket } from "./data";
import { useTicketStore } from "./data";
import CommentItem from "./CommentItem.vue";
import CommunicationItem from "./CommunicationItem.vue";

type SocketData = {
ticket_id: string;
};

const { ticket } = useTicketStore();

ticket.getCommunications
.submit()
.then(() => (isCommunicationsLoaded.value = true));
Expand Down
3 changes: 2 additions & 1 deletion desk/src/pages/desk/ticket/CustomFieldList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
<script setup lang="ts">
import { isEmpty } from "lodash";
import { computed } from "vue";
import { ticket } from "./data";
import { useTicketStore } from "./data";
import IconTeams from "~icons/espresso/teams";
import IconWebLink from "~icons/espresso/web-link";

const { ticket } = useTicketStore();
const fields = computed(() => ticket.doc?.custom_fields);
</script>
17 changes: 7 additions & 10 deletions desk/src/pages/desk/ticket/OpenTicketList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,12 @@
<IconCaretDown v-else class="h-4 w-4 text-gray-600" />
</div>
<div v-if="isExpanded" class="flex flex-col gap-2 pt-4">
<div v-for="ticket in tickets" :key="ticket.name">
<router-link
:to="ticket.to"
target="_blank"
class="flex items-start gap-2"
>
<div v-for="t in tickets" :key="t.name">
<router-link :to="t.to" target="_blank" class="flex items-start gap-2">
<div class="flex h-5 w-5 items-center justify-center">
<IconWebLink class="h-5 w-5 text-gray-600" />
</div>
<div class="text-base text-gray-800">{{ ticket.subject }}</div>
<div class="text-base text-gray-800">{{ t.subject }}</div>
</router-link>
</div>
</div>
Expand All @@ -36,7 +32,7 @@ import { isEmpty } from "lodash";
import { computed, ref } from "vue";
import { createListResource } from "frappe-ui";
import { AGENT_PORTAL_TICKET } from "@/router";
import { ticket } from "./data";
import { useTicketStore } from "./data";
import IconWebLink from "~icons/espresso/web-link";
import IconCaretDown from "~icons/ph/caret-down";
import IconCaretUp from "~icons/ph/caret-up";
Expand All @@ -54,9 +50,10 @@ class Ticket {
}
}

const { ticket } = useTicketStore();
const isExpanded = ref(false);

const t = createListResource({
const ticketRes = createListResource({
doctype: "HD Ticket",
fields: ["name", "subject"],
filters: {
Expand All @@ -68,6 +65,6 @@ const t = createListResource({
});

const tickets = computed(
() => t.data?.map((t: Ticket) => new Ticket(t.name, t.subject)) || []
() => ticketRes.data?.map((t: Ticket) => new Ticket(t.name, t.subject)) || []
);
</script>
11 changes: 6 additions & 5 deletions desk/src/pages/desk/ticket/SideBar.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="flex">
<TabGroup vertical>
<TabPanels v-if="sidebar.isVisible" class="main-panel h-full">
<TabPanels v-if="sidebar.isExpanded" class="main-panel h-full">
<TabPanel v-for="item in items" :key="item.name" class="h-full">
<component :is="item.component" class="h-full" />
</TabPanel>
Expand All @@ -11,10 +11,10 @@
<div
class="flex h-7 w-7 items-center justify-center rounded-lg text-gray-600"
:class="{
'bg-gray-200': sidebar.isVisible && selected,
'text-gray-900': sidebar.isVisible && selected,
'bg-gray-200': sidebar.isExpanded && selected,
'text-gray-900': sidebar.isExpanded && selected,
}"
@click="sidebar.isVisible = true"
@click="sidebar.isExpanded = true"
>
<component :is="item.icon" />
</div>
Expand All @@ -26,14 +26,15 @@

<script setup lang="ts">
import { TabGroup, TabList, Tab, TabPanels, TabPanel } from "@headlessui/vue";
import { sidebar } from "./data";
import { useTicketStore } from "./data";
import ContactDetails from "./ContactDetails.vue";
import TicketDetails from "./TicketDetails.vue";
import TicketHistory from "./TicketHistory.vue";
import IconActivity from "~icons/espresso/activity";
import IconAlert from "~icons/espresso/alert-circle";
import IconDetails from "~icons/espresso/details";

const { sidebar } = useTicketStore();
const items = [
{
name: "Ticket Details",
Expand Down
5 changes: 3 additions & 2 deletions desk/src/pages/desk/ticket/TicketDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Button
appearance="minimal"
icon="x"
@click="sidebar.isVisible = false"
@click="sidebar.isExpanded = false"
/>
</div>
<div class="my-6 flex flex-col justify-between gap-3.5">
Expand Down Expand Up @@ -113,14 +113,15 @@ import { useTicketPriorityStore } from "@/stores/ticketPriority";
import { useTicketStatusStore } from "@/stores/ticketStatus";
import { useTicketTypeStore } from "@/stores/ticketType";
import { createToast } from "@/utils/toasts";
import { sidebar, ticket } from "./data";
import { useTicketStore } from "./data";

const agentStore = useAgentStore();
const keymapStore = useKeymapStore();
const teamStore = useTeamStore();
const ticketPriorityStore = useTicketPriorityStore();
const ticketStatusStore = useTicketStatusStore();
const ticketTypeStore = useTicketTypeStore();
const { sidebar, ticket } = useTicketStore();

const isSaveButtonVisible = ref(false);

Expand Down
6 changes: 4 additions & 2 deletions desk/src/pages/desk/ticket/TicketHistory.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Button
appearance="minimal"
icon="x"
@click="sidebar.isVisible = false"
@click="sidebar.isExpanded = false"
/>
</div>
<div class="overflow-scroll px-4">
Expand Down Expand Up @@ -34,7 +34,7 @@
import { computed, ComputedRef } from "vue";
import { Button, createListResource, Tooltip } from "frappe-ui";
import dayjs from "dayjs";
import { sidebar, ticket } from "./data";
import { useTicketStore } from "./data";
import IconDot from "~icons/ph/dot-bold";

class Activity {
Expand All @@ -59,6 +59,8 @@ class Activity {
}
}

const { sidebar, ticket } = useTicketStore();

const r = createListResource({
doctype: "HD Ticket Activity",
fields: ["name", "creation", "action", "owner"],
Expand Down
3 changes: 2 additions & 1 deletion desk/src/pages/desk/ticket/TicketSingle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<script setup lang="ts">
import { ref, onUnmounted } from "vue";
import { useConfigStore } from "@/stores/config";
import { deinit, init, ticket } from "./data";
import { useTicketStore } from "./data";
import ConversationBox from "./ConversationBox.vue";
import ResponseEditor from "./editor/ResponseEditor.vue";
import SideBar from "./SideBar.vue";
Expand All @@ -27,6 +27,7 @@ const props = defineProps({
required: true,
},
});
const { init, deinit, ticket } = useTicketStore();
const isResLoaded = ref(false);
const configStore = useConfigStore();

Expand Down
3 changes: 2 additions & 1 deletion desk/src/pages/desk/ticket/TopBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import { Tooltip } from "frappe-ui";
import { useClipboard } from "@vueuse/core";
import dayjs from "dayjs";
import { AGENT_PORTAL_TICKET_LIST } from "@/router";
import { ticket } from "./data";
import { useTicketStore } from "./data";
import { createToast } from "@/utils/toasts";
import IconAtSign from "~icons/espresso/at-sign";
import IconCaretLeft from "~icons/ph/caret-left";
Expand All @@ -52,6 +52,7 @@ import IconWeb from "~icons/espresso/web";

const { copy } = useClipboard();
const router = useRouter();
const { ticket } = useTicketStore();

const date = computed(() => dayjs(ticket.doc.modified).tz(dayjs.tz.guess()));
const dateShort = computed(() => date.value.fromNow());
Expand Down
118 changes: 69 additions & 49 deletions desk/src/pages/desk/ticket/data.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,30 @@
import { reactive } from "vue";
import { defineStore } from "pinia";
import { createDocumentResource } from "frappe-ui";
import { socket } from "@/socket";
import { createToast } from "@/utils/toasts";

export let ticket = null;

export const sidebar = reactive({
isVisible: true,
});
export const useTicketStore = defineStore("ticket", () => {
const sidebar = reactive({
isExpanded: true,
});

export const editor = reactive({
isExpanded: false,
content: "",
attachments: [],
cc: [],
bcc: [],
isCcVisible: false,
isBccVisible: false,
});
const editor = reactive({
isExpanded: false,
content: "",
attachments: [],
cc: [],
bcc: [],
isCcVisible: false,
isBccVisible: false,
tiptap: null,
});

/**
* Initialize necessary data, to be shared across components. This contains
* only shareable data. Individual sources are defined and used in respective
* components.
*/
export async function init(id: number) {
ticket = createDocumentResource({
const ticket = createDocumentResource({
doctype: "HD Ticket",
fields: ["name", "custom_fields"],
name: id,
auto: true,
name: 747,
auto: false,
whitelistedMethods: {
markSeen: "mark_seen",
assign: "assign_agent",
Expand Down Expand Up @@ -65,33 +60,58 @@ export async function init(id: number) {
},
});

await ticket.get.promise;
/**
* Initialize necessary data, to be shared across components. This contains
* only shareable data. Individual sources are defined and used in respective
* components.
*/
async function init(name: number) {
// ticket.update({ name });
ticket.reload();
await ticket.get.promise;
startListening();
}

socket.on("helpdesk:ticket-update", (data) => {
if (parseInt(data.name) == ticket.doc.name) ticket.reload();
});
/**
* Reset all states, and stop listening to socket events
*/
function deinit() {
clean();
endListening();
}

socket.on("helpdesk:ticket-assignee-update", (data) => {
if (parseInt(data.name) == ticket.doc.name) ticket.getAssignees.reload();
});
}
function startListening() {
socket.on("helpdesk:ticket-update", (data) => {
if (parseInt(data.name) === ticket.doc.name) ticket.reload();
});

socket.on("helpdesk:ticket-assignee-update", (data) => {
if (parseInt(data.name) === ticket.doc.name) ticket.getAssignees.reload();
});
}

export function clean() {
editor.isExpanded = false;
editor.content = "";
editor.attachments = [];
editor.cc = [];
editor.bcc = [];
editor.isCcVisible = false;
editor.isBccVisible = false;
sidebar.isVisible = true;
}
function endListening() {
socket.off("helpdesk:ticket-update");
socket.off("helpdesk:ticket-assignee-update");
}

/**
* Reset all states, and stop listening to socket events
*/
export function deinit() {
clean();
socket.off("helpdesk:ticket-update");
socket.off("helpdesk:ticket-assignee-update");
}
function clean() {
editor.isExpanded = false;
editor.content = "";
editor.attachments = [];
editor.cc = [];
editor.bcc = [];
editor.isCcVisible = false;
editor.isBccVisible = false;
sidebar.isExpanded = true;
}

return {
clean,
deinit,
editor,
init,
sidebar,
ticket,
};
});
Loading