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

refactor: comment #1612

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
30 changes: 19 additions & 11 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,28 @@ module.exports = {
node: true,
},
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:json/recommended",
"plugin:vue/vue3-recommended",
"plugin:tailwindcss/recommended",
"plugin:prettier/recommended",
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:json/recommended',
'plugin:vue/vue3-recommended',
'plugin:tailwindcss/recommended',
'plugin:prettier/recommended',
],
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
parser: "@typescript-eslint/parser",
ecmaVersion: 'latest',
sourceType: 'module',
parser: '@typescript-eslint/parser',
},
rules: {
"tailwindcss/no-custom-classname": "off",
"vue/multi-word-component-names": "off",
'tailwindcss/no-custom-classname': 'off',
'vue/multi-word-component-names': 'off',
'prettier/prettier': [
'warn',
{
singleQuote: true,
semi: true,
useTabs: false,
},
],
},
};
1 change: 1 addition & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"singleQuote": true,
"useTabs": false
}
39 changes: 21 additions & 18 deletions desk/index.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Helpdesk</title>
</head>
<body>
<div id="app"></div>
<div id="modals"></div>
<div id="popovers"></div>
<script type="module" src="/src/main.js"></script>
<script>
window.csrf_token = "{{ csrf_token }}"
window.frappe_version = "{{ frappe_version }}"
window.helpdesk_version = "{{ helpdesk_version }}"
window.site_name = "{{ site_name }}"
</script>
</body>

<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Helpdesk</title>
</head>

<body>
<div id="app"></div>
<div id="modals"></div>
<div id="popovers"></div>
<script type="module" src="/src/main.js"></script>
<script>
window.csrf_token = "{{ csrf_token }}"
window.frappe_version = "{{ frappe_version }}"
window.helpdesk_version = "{{ helpdesk_version }}"
window.site_name = "{{ site_name }}"
</script>
</body>

</html>
1 change: 1 addition & 0 deletions desk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"vue": "^3.2.47",
"vue-echarts": "^6.5.4",
"vue-router": "^4.1.6",
"vue-sonner": "^1.0.2",
"vuedraggable": "^4.1.0",
"zod": "^3.21.4"
},
Expand Down
6 changes: 3 additions & 3 deletions desk/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 14 additions & 14 deletions desk/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,39 @@
<span class="fixed inset-0">
<RouterView class="antialiased" />
<Toasts />
<Toaster position="top-right" rich-colors />
<KeymapDialog />
</span>
</template>

<script setup lang="ts">
import { provide, ref, onMounted } from "vue";
import { Toasts } from "frappe-ui";
import { createToast } from "@/utils";
import { useConfigStore } from "@/stores/config";
import KeymapDialog from "@/pages/KeymapDialog.vue";
import { provide, ref, onMounted } from 'vue';
import { Toasts } from 'frappe-ui';
import { Toaster } from 'vue-sonner';
import { createToast } from '@/utils';
import { useConfigStore } from '@/stores/config';
import KeymapDialog from '@/pages/KeymapDialog.vue';

useConfigStore();

const viewportWidth = ref(
Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
);

provide("viewportWidth", viewportWidth);
provide('viewportWidth', viewportWidth);

onMounted(async () => {
window.addEventListener("online", () => {
window.addEventListener('online', () => {
createToast({
title: "You are now online",
icon: "wifi",
iconClasses: "stroke-green-600",
title: 'You are now online',
type: 'success',
});
});

window.addEventListener("offline", () => {
window.addEventListener('offline', () => {
createToast({
title: "You are now offline",
icon: "wifi-off",
iconClasses: "stroke-red-600",
title: 'You are now offline',
type: 'warning',
});
});
});
Expand Down
7 changes: 3 additions & 4 deletions desk/src/assets/logos/helpdesk.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions desk/src/assets/misc/ticket-divider.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
206 changes: 206 additions & 0 deletions desk/src/components/AppSidebar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
<template>
<div
class="z-0 flex min-w-[256px] max-w-[256px] select-none flex-col border-r border-gray-200 bg-gray-50 p-2 text-base duration-300 ease-in-out"
>
<Dropdown :options="dropdownOptions" class="mb-2">
<template #default="{ open }">
<button
class="flex w-[15rem] items-center rounded-md p-2 text-left"
:class="open ? 'bg-white shadow-sm' : 'hover:bg-gray-200'"
>
<img :src="HelpdeskLogo" class="h-8 w-8 rounded" />
<div class="ml-2 flex flex-col">
<div class="text-base font-medium leading-none text-gray-900">
Helpdesk
</div>
<div
class="mt-1 hidden text-sm leading-none text-gray-700 sm:inline"
>
{{ authStore.userName }}
</div>
</div>
<FeatherIcon
name="chevron-down"
class="ml-auto h-5 w-5 text-gray-700"
/>
</button>
</template>
</Dropdown>
<SidebarLink
label="Search"
class="mb-1"
:icon="LucideSearch"
:on-click="() => openCommandPalette()"
>
<template #right>
<span class="flex items-center gap-0.5 font-medium text-gray-600">
<component :is="device.modifierIcon" class="h-3 w-3" />
<span>K</span>
</span>
</template>
</SidebarLink>
<!-- <span class="mb-1"> -->
<!-- <div -->
<!-- v-if="notificationStore.unread" -->
<!-- class="absolute z-20 h-1.5 w-1.5 translate-x-6 translate-y-1 rounded-full bg-gray-800" -->
<!-- theme="gray" -->
<!-- variant="solid" -->
<!-- /> -->
<!-- <SidebarLink -->
<!-- class="relative" -->
<!-- label="Notifications" -->
<!-- :icon="LucideInbox" -->
<!-- :on-click="() => notificationStore.toggle()" -->
<!-- :is-expanded="isExpanded" -->
<!-- > -->
<!-- <template #right> -->
<!-- <Badge -->
<!-- v-if="isExpanded && notificationStore.unread" -->
<!-- :label="notificationStore.unread" -->
<!-- theme="gray" -->
<!-- variant="subtle" -->
<!-- /> -->
<!-- </template> -->
<!-- </SidebarLink> -->
<!-- </span> -->
<div class="space-y-1">
<SidebarLink
v-for="option in menuOptions"
v-bind="option"
:key="option.label"
:is-active="option.to?.includes(route.name.toString())"
/>
</div>
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import { storeToRefs } from 'pinia';
import { Dropdown } from 'frappe-ui';
import { useAuthStore } from '@/stores/auth';
import { useKeymapStore } from '@/stores/keymap';
// import { useNotificationStore } from '@/stores/notification';
import { useSidebarStore } from '@/stores/sidebar';
import {
AGENT_PORTAL_AGENT_LIST,
AGENT_PORTAL_CANNED_RESPONSE_LIST,
AGENT_PORTAL_CONTACT_LIST,
AGENT_PORTAL_CUSTOMER_LIST,
AGENT_PORTAL_DASHBOARD,
AGENT_PORTAL_ESCALATION_RULE_LIST,
AGENT_PORTAL_TEAM_LIST,
AGENT_PORTAL_TICKET_LIST,
AGENT_PORTAL_TICKET_TYPE_LIST,
CUSTOMER_PORTAL_LANDING,
} from '@/router';
import { useDevice } from '@/composables';
import { SidebarLink } from '@/components';
// import UserMenu from './UserMenu.vue';
import HelpdeskLogo from '@/assets/logos/helpdesk.svg';
import LucideArrowLeftFromLine from '~icons/lucide/arrow-left-from-line';
import LucideArrowRightFromLine from '~icons/lucide/arrow-right-from-line';
import LucideArrowUpFromLine from '~icons/lucide/arrow-up-from-line';
import LucideBookOpen from '~icons/lucide/book-open';
import LucideCloudLightning from '~icons/lucide/cloud-lightning';
import LucideContact2 from '~icons/lucide/contact-2';
import LucideFolderOpen from '~icons/lucide/folder-open';
import LucideInbox from '~icons/lucide/inbox';
import LucideLayoutGrid from '~icons/lucide/layout-grid';
import LucideSearch from '~icons/lucide/search';
import LucideTicket from '~icons/lucide/ticket';
import LucideUser from '~icons/lucide/user';
import LucideUserCircle2 from '~icons/lucide/user-circle-2';
import LucideUsers from '~icons/lucide/users';

const route = useRoute();
const authStore = useAuthStore();
const keymapStore = useKeymapStore();
// const notificationStore = useNotificationStore();
const device = useDevice();

const menuOptions = computed(() =>
[
{
label: 'Tickets',
icon: LucideTicket,
to: AGENT_PORTAL_TICKET_LIST,
},
{
label: 'Dashboard',
icon: LucideLayoutGrid,
to: AGENT_PORTAL_DASHBOARD,
},
{
label: 'Agents',
icon: LucideUser,
to: AGENT_PORTAL_AGENT_LIST,
hide: !authStore.isAgent,
},
{
label: 'Knowledge base',
icon: LucideBookOpen,
to: 'DeskKBHome',
isBeta: true,
},
{
label: 'Teams',
icon: LucideUsers,
to: AGENT_PORTAL_TEAM_LIST,
hide: !authStore.isAgent,
},
{
label: 'Escalation rules',
icon: LucideArrowUpFromLine,
to: AGENT_PORTAL_ESCALATION_RULE_LIST,
isBeta: true,
hide: !authStore.isAgent,
},
{
label: 'Ticket types',
icon: LucideFolderOpen,
to: AGENT_PORTAL_TICKET_TYPE_LIST,
hide: true,
},
{
label: 'Canned responses',
icon: LucideCloudLightning,
to: AGENT_PORTAL_CANNED_RESPONSE_LIST,
isBeta: true,
hide: !authStore.isAgent,
},
{
label: 'Customers',
icon: LucideUserCircle2,
to: AGENT_PORTAL_CUSTOMER_LIST,
hide: !authStore.isAgent,
},
{
label: 'Contacts',
icon: LucideContact2,
to: AGENT_PORTAL_CONTACT_LIST,
hide: !authStore.isAgent,
},
].filter((option) => !option.hide)
);

const dropdownOptions = [
// {
// label: 'Shortcuts',
// icon: 'command',
// onClick: () => keymapStore.toggleVisibility(true),
// },
{
label: 'Logout',
icon: 'log-out',
onClick: () => authStore.logout(),
},
];

function openCommandPalette() {
window.dispatchEvent(
new KeyboardEvent('keydown', { key: 'k', metaKey: true })
);
}
</script>
Loading