Skip to content

Commit

Permalink
feat: move to category and create category
Browse files Browse the repository at this point in the history
  • Loading branch information
RitvikSardana committed Jan 10, 2025
1 parent 7fdfc6e commit 5155935
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 27 deletions.
21 changes: 20 additions & 1 deletion desk/src/components/ListViewBuilder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@
</div>
</ListRowItem>
</ListRows>
<ListSelectBanner v-if="props.options.showSelectBanner">
<template #actions="{ selections }">
<Dropdown :options="selectBannerOptions(selections)">
<Button icon="more-horizontal" variant="ghost" />
</Dropdown>
</template>
</ListSelectBanner>
</ListView>

<!-- List Footer -->
Expand Down Expand Up @@ -103,8 +110,10 @@ import {
ListRowItem,
ListHeader,
ListHeaderItem,
ListSelectBanner,
Badge,
FeatherIcon,
Dropdown,
} from "frappe-ui";
import {
Expand All @@ -114,7 +123,6 @@ import {
Reload,
} from "@/components/view-controls";
import { dayjs } from "@/dayjs";
import FadedScrollableDiv from "./FadedScrollableDiv.vue";
import ListRows from "./ListRows.vue";
import { useScreenSize } from "@/composables/screen";
import EmptyState from "./EmptyState.vue";
Expand All @@ -134,6 +142,8 @@ interface P {
statusMap?: Record<string, BadgeStatus>;
view?: View;
groupByActions?: Array<any>;
showSelectBanner?: boolean;
selectBannerActions?: Record<string, any>;
};
}
Expand Down Expand Up @@ -177,6 +187,15 @@ const emptyState = computed(() => {
return props.options?.emptyState || defaultEmptyState;
});
function selectBannerOptions(selections: Set<string>) {
return props.options.selectBannerActions.map((action) => {
return {
...action,
onClick: () => action.onClick(selections),
};
});
}
const list = createResource({
url: "helpdesk.api.doc.get_list_data",
params: defaultParams,
Expand Down
2 changes: 1 addition & 1 deletion desk/src/components/frappe-ui/Link.vue
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ const options = createResource({
transform: (data) => {
let allData = data.map((option) => {
return {
label: option.value,
value: option.value,
label: option?.label || option.value,
};
});
// if (!props.hideMe && props.doctype == 'User') {
Expand Down
36 changes: 36 additions & 0 deletions desk/src/components/knowledge-base/MoveToCategoryModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<template>
<Dialog v-model="showDialog" :options="{ title: 'Move To', actions }">
<template #body-content>
<div class="flex flex-col flex-1 gap-3">
<Link
class="form-control"
doctype="HD Article Category"
placeholder="Select Category"
v-model="category"
label="Category"
/>
</div>
</template>
</Dialog>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { Dialog } from "frappe-ui";
import { Link } from "@/components";
const emit = defineEmits(["move"]);
const showDialog = defineModel<boolean>();
const category = ref("");
const actions = [
{
label: "Move",
variant: "solid",
onClick: () => emit("move", category.value),
},
];
</script>

<style scoped></style>
76 changes: 59 additions & 17 deletions desk/src/pages/knowledge-base/KnowledgeBase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
/>
<CategoryModal
:edit="editTitle"
v-model="showDialog"
v-model="showCategoryModal"
v-model:title="category.title"
@update="handleCategoryUpdate"
@create="handleCategoryCreate"
/>
<MoveToCategoryModal v-model="moveToModal" @move="handleMoveToCategory" />
</div>
</template>

Expand All @@ -43,23 +44,28 @@ import {
updateCategoryTitle,
deleteCategory,
newCategory,
moveToCategory,
} from "@/stores/knowledgeBase";
import LayoutHeader from "@/components/LayoutHeader.vue";
import ListViewBuilder from "@/components/ListViewBuilder.vue";
import CategoryModal from "@/components/knowledge-base/CategoryModal.vue";
import MoveToCategoryModal from "@/components/knowledge-base/MoveToCategoryModal.vue";
import { createToast } from "@/utils";
const router = useRouter();
const showDialog = ref(false);
const category = reactive({
title: "",
id: "",
});
const _title = ref("");
const editTitle = ref(false);
const listViewRef = ref(null);
const editTitle = ref(false);
// modals state
const showCategoryModal = ref(false);
const moveToModal = ref(false);
const headerOptions = [
{
Expand All @@ -68,20 +74,14 @@ const headerOptions = [
onClick: () => {
resetState();
editTitle.value = false;
showDialog.value = true;
showCategoryModal.value = true;
},
},
{
label: "Article",
icon: "file",
onClick: () => {
router.push({ name: "NewArticle" });
// router.push({
// name: "NewArticle",
// query: {
// category: "ABC",
// },
// });
},
},
];
Expand All @@ -106,7 +106,7 @@ const groupByActions = [
icon: "edit",
onClick: (groupedRow) => {
editTitle.value = true;
showDialog.value = true;
showCategoryModal.value = true;
category.title = groupedRow.group.label;
category.id = groupedRow.group.value;
_title.value = groupedRow.group.label;
Expand All @@ -120,17 +120,57 @@ const groupByActions = [
},
},
];
const listSelections = ref(new Set());
const selectBannerActions = [
{
label: "Move To",
icon: "corner-up-right",
onClick: (selections: Set<string>) => {
listSelections.value = selections;
moveToModal.value = true;
},
},
];
function handleMoveToCategory(category: string) {
moveToCategory.submit(
{
category,
articles: Array.from(listSelections.value),
},
{
onSuccess: () => {
listViewRef.value.reload();
moveToModal.value = false;
createToast({
title: "Articles moved successfully",
icon: "check",
iconClasses: "text-green-600",
});
},
}
);
}
function handleCategoryCreate() {
console.log("Create", category.title);
newCategory.submit(
{
category_name: category.title,
title: category.title,
},
{
onSuccess: () => {
onSuccess: (data: any) => {
listViewRef.value.reload();
showDialog.value = false;
showCategoryModal.value = false;
router.push({
name: "Article",
params: {
articleId: data.article,
},
query: {
category: data.category,
title: category.title,
},
});
createToast({
title: "Category Created Successfully",
icon: "check",
Expand All @@ -152,7 +192,7 @@ function handleCategoryCreate() {
function handleCategoryUpdate() {
// if same title do nothing
if (category.title === _title.value) {
showDialog.value = false;
showCategoryModal.value = false;
editTitle.value = false;
return;
}
Expand All @@ -166,7 +206,7 @@ function handleCategoryUpdate() {
{
onSuccess: () => {
listViewRef.value.reload();
showDialog.value = false;
showCategoryModal.value = false;
editTitle.value = false;
createToast({
title: "Category Updated Successfully",
Expand Down Expand Up @@ -249,6 +289,8 @@ const options = {
},
},
groupByActions,
showSelectBanner: true,
selectBannerActions,
};
usePageMeta(() => {
Expand Down
28 changes: 20 additions & 8 deletions desk/src/stores/knowledgeBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,14 @@ export const deleteRes = createResource({
// Category

export const newCategory = createResource({
url: "frappe.client.insert",
makeParams({ category_name }) {
url: "helpdesk.api.knowledge_base.create_category",
makeParams({ title }) {
return {
doc: {
doctype: "HD Article Category",
category_name,
},
title,
};
},
validate({ doc }) {
if (!doc.category_name) throw "Title is required";
validate(title: string) {
if (!title) throw "Title is required";
},
});

Expand All @@ -62,3 +59,18 @@ export const deleteCategory = createResource({
if (!name) throw "Category is required";
},
});

export const moveToCategory = createResource({
url: "helpdesk.api.knowledge_base.move_to_category",
makeParams({ category,articles }) {
return {
category,
articles
};
},
validate({ category,articles }) {
if (!category) throw "Category is required";
if (!articles) throw "Articles are required";
}

})
15 changes: 15 additions & 0 deletions helpdesk/api/knowledge_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ def get_article(name: str):
return article


@frappe.whitelist()
def create_category(title: str):
category = frappe.new_doc("HD Article Category", category_name=title).insert()
article = frappe.new_doc(
"HD Article", title="New Article", category=category.name
).insert()
return {"article": article.name, "category": category.name}


@frappe.whitelist()
def delete_category(name: str):
try:
Expand All @@ -42,3 +51,9 @@ def delete_category(name: str):
frappe.delete_doc("HD Article Category", name)
except Exception as e:
frappe.db.rollback()


@frappe.whitelist()
def move_to_category(category, articles):
for article in articles:
frappe.db.set_value("HD Article", article, "category", category)

0 comments on commit 5155935

Please sign in to comment.