Skip to content

Commit

Permalink
feat: added column selector
Browse files Browse the repository at this point in the history
  • Loading branch information
sumitbhanushali committed Feb 21, 2024
1 parent 10b8b95 commit c625c47
Show file tree
Hide file tree
Showing 8 changed files with 284 additions and 24 deletions.
43 changes: 43 additions & 0 deletions desk/src/components/ColumnItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<template>
<div
class="flex cursor-grab items-center justify-between gap-6 rounded px-2 py-1.5 text-base text-gray-800 hover:bg-gray-100"
>
<div class="flex items-center gap-2">
<DragIcon class="h-3.5" />
<div>{{ column.label }}</div>
</div>
<div class="flex cursor-pointer items-center gap-1">
<Button
variant="ghost"
class="!h-5 w-5 !p-1"
@click="emit('remove', column)"
>
<FeatherIcon name="x" class="h-3.5" />
</Button>
</div>
</div>
</template>
<script setup lang="ts">
import DragIcon from "@/components/icons/DragIcon.vue";
import { watchDebounced } from "@vueuse/core";
const props = defineProps({
column: {
type: Object,
required: true,
},
});
const emit = defineEmits(["edit", "remove", "update"]);
watchDebounced(
() => props.column.width,
(val, old_val) => {
val = val.replace(/[^\d.]/g, "");
old_val = old_val.replace(/[^\d.]/g, "");
if (Math.abs(val - old_val) > 1) return;
emit("update");
},
{ debounce: 1000 }
);
</script>
105 changes: 105 additions & 0 deletions desk/src/components/ColumnSettings.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<template>
<NestedPopover>
<template #target>
<Button label="Columns">
<template #prefix>
<ColumnsIcon class="h-4" />
</template>
</Button>
</template>
<template #body>
<div
class="my-2 rounded-lg border border-gray-100 bg-white p-1.5 shadow-xl"
>
<div v-if="!edit">
<Draggable
:list="columns"
item-key="key"
class="list-group"
@end="update"
>
<template #item="{ element }">
<ColumnItem :column="element" @remove="removeColumn" />
</template>
</Draggable>
<div class="mt-1.5 flex flex-col gap-1 border-t pt-1.5">
<Autocomplete
value=""
:options="fields"
@change="(e) => addColumn(e)"
>
<template #target="{ togglePopover }">
<Button
class="w-full !justify-start !text-gray-600"
variant="ghost"
label="Add Column"
@click="togglePopover()"
>
<template #prefix>
<FeatherIcon name="plus" class="h-4" />
</template>
</Button>
</template>
</Autocomplete>
</div>
</div>
</div>
</template>
</NestedPopover>
</template>

<script setup lang="ts">
import { ref } from "vue";
import ColumnsIcon from "@/components/icons/ColumnsIcon.vue";
import ColumnItem from "@/components/ColumnItem.vue";
import NestedPopover from "@/components/NestedPopover.vue";
import { Autocomplete } from "frappe-ui";
import Draggable from "vuedraggable";
let emit = defineEmits(["event:column"]);
let edit = ref(false);
let props = defineProps({
fields: {
type: Array,
required: true,
},
columns: {
type: Array,
required: true,
},
});
function addColumn(c) {
let columnEvent = {
event: "add",
data: {
label: c.label,
type: c.type,
key: c.value,
width: "10rem",
},
};
emit("event:column", columnEvent);
}
function update() {
let columnEvent = {
event: "update",
data: props.columns,
};
emit("event:column", columnEvent);
}
function removeColumn(c) {
if (c.key === "name" || c.key === "_assign") {
return;
// TODO
}
let columnEvent = {
event: "remove",
data: c,
};
emit("event:column", columnEvent);
}
</script>
26 changes: 17 additions & 9 deletions desk/src/components/ViewControls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,31 @@

<div class="flex-none px-1">
<Filter
:filters="props.filter.filters"
:filterable-fields="props.filter.filterableFields"
:filters="filter.filters"
:filterable-fields="filter.filterableFields"
@event:filter="(e) => emitToParent(e, 'event:filter')"
/>
</div>
<div class="pe-2 flex-none">
<Sort
:sortable-fields="props.sort.sortableFields"
:sorts="props.sort.sorts"
:sortable-fields="sort.sortableFields"
:sorts="sort.sorts"
@event:sort="(e) => emitToParent(e, 'event:sort')"
/>
</div>
<!-- <div class="flex-none pe-2">
<p class="text-lg">View Settings</p>
</div> -->
<div class="flex-none px-1">
<ColumnSettings
:fields="column.fields"
:columns="column.columns"
@event:column="(e) => emitToParent(e, 'event:column')"
/>
</div>
</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { Filter, Sort } from "@/components";
import { Filter, Sort, ColumnSettings } from "@/components";
import { Dropdown, FeatherIcon } from "frappe-ui";
import { useAuthStore } from "@/stores/auth";
Expand All @@ -55,6 +59,10 @@ const props = defineProps({
type: Object,
required: true,
},
column: {
type: Object,
required: true,
},
});
const presetFilters = [
Expand Down Expand Up @@ -148,7 +156,7 @@ function getPresetFilters(status) {
};
}
const emit = defineEmits(["event:filter", "event:sort"]);
const emit = defineEmits(["event:filter", "event:sort", "event:column"]);
function emitToParent(data, event) {
if (event === "event:filter") {
Expand Down
16 changes: 16 additions & 0 deletions desk/src/components/icons/ColumnsIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<template>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M8.07548 1.50005C8.05087 1.49632 8.02566 1.49438 8 1.49438C7.97434 1.49438 7.94914 1.49632 7.92452 1.50005H3C1.89543 1.50005 1 2.39548 1 3.50005V12.5C1 13.6046 1.89543 14.5 3 14.5H7.92511C7.94954 14.5037 7.97455 14.5056 8 14.5056C8.02545 14.5056 8.05046 14.5037 8.07489 14.5H13C14.1046 14.5 15 13.6046 15 12.5V3.50005C15 2.39548 14.1046 1.50005 13 1.50005H8.07548ZM7.5 2.50005H3C2.44772 2.50005 2 2.94776 2 3.50005V12.5C2 13.0523 2.44772 13.5 3 13.5H7.5L7.5 2.50005ZM8.5 13.5L8.5 2.50005H13C13.5523 2.50005 14 2.94776 14 3.50005V12.5C14 13.0523 13.5523 13.5 13 13.5H8.5Z"
fill="currentColor"
/>
</svg>
</template>
16 changes: 16 additions & 0 deletions desk/src/components/icons/DragIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<template>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M13 6.75C12.3096 6.75 11.75 6.19036 11.75 5.5C11.75 4.80964 12.3096 4.25 13 4.25C13.6904 4.25 14.25 4.80964 14.25 5.5C14.25 6.19036 13.6904 6.75 13 6.75ZM3 6.75C2.30964 6.75 1.75 6.19036 1.75 5.5C1.75 4.80964 2.30964 4.25 3 4.25C3.69036 4.25 4.25 4.80964 4.25 5.5C4.25 6.19036 3.69036 6.75 3 6.75ZM6.75 5.5C6.75 6.19036 7.30964 6.75 8 6.75C8.69036 6.75 9.25 6.19036 9.25 5.5C9.25 4.80964 8.69036 4.25 8 4.25C7.30964 4.25 6.75 4.80964 6.75 5.5ZM13 11.75C12.3096 11.75 11.75 11.1904 11.75 10.5C11.75 9.80964 12.3096 9.25 13 9.25C13.6904 9.25 14.25 9.80964 14.25 10.5C14.25 11.1904 13.6904 11.75 13 11.75ZM1.75 10.5C1.75 11.1904 2.30964 11.75 3 11.75C3.69036 11.75 4.25 11.1904 4.25 10.5C4.25 9.80964 3.69036 9.25 3 9.25C2.30964 9.25 1.75 9.80964 1.75 10.5ZM8 11.75C7.30964 11.75 6.75 11.1904 6.75 10.5C6.75 9.80964 7.30964 9.25 8 9.25C8.69036 9.25 9.25 9.80964 9.25 10.5C9.25 11.1904 8.69036 11.75 8 11.75Z"
fill="currentColor"
/>
</svg>
</template>
1 change: 1 addition & 0 deletions desk/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export { default as Filter } from "./Filter.vue";
export { default as LayoutHeader } from "./LayoutHeader.vue";
export { default as Sort } from "./Sort.vue";
export { default as MultipleAvatar } from "./MultipleAvatar.vue";
export { default as ColumnSettings } from "./ColumnSettings.vue";
64 changes: 60 additions & 4 deletions desk/src/pages/tickets/TicketsAgent2.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@
<ViewControls
:filter="{ filters: filters, filterableFields: filterableFields.data }"
:sort="{ sorts: sorts, sortableFields: sortableFields.data }"
:column="{
fields: fields,
columns: columns,
}"
@event:sort="processSorts"
@event:filter="processFilters"
@event:column="processColumns"
/>
<TicketsAgentList2
:rows="rows"
:rows="items"
:columns="columns"
:page-length-count="pageLength"
:options="{
Expand All @@ -48,10 +53,14 @@ let storage = useStorage("tickets_agent", {
filters: [],
sorts: [],
sortsToApply: "modified desc",
columns: [],
rows: [],
});
let columns = ref([]);
let rows = ref([]);
let items = ref([]);
let columns = ref(storage.value.columns ? storage.value.columns : []);
let rows = ref(storage.value.rows ? storage.value.rows : []);
let fields = ref([]);
let rowCount = ref(0);
let totalCount = ref(0);
Expand All @@ -70,6 +79,8 @@ const tickets = createResource({
filters: filtersToApply,
order_by: sortsToApply,
page_length: pageLength.value,
columns: columns.value.length ? columns.value : undefined,
rows: rows.value.length ? rows.value : undefined,
},
auto: true,
transform(data) {
Expand All @@ -86,7 +97,9 @@ const tickets = createResource({
},
onSuccess(data) {
columns.value = data.columns;
rows.value = data.data;
rows.value = data.rows;
items.value = data.data;
fields.value = data.fields;
rowCount.value = data.row_count;
totalCount.value = data.total_count;
},
Expand Down Expand Up @@ -117,6 +130,49 @@ function updatePageLength(value) {
tickets.reload();
}
function processColumns(columnEvent) {
if (columnEvent.event === "add") {
tickets.update({
params: {
order_by: sortsToApply,
filters: filtersToApply,
page_length: pageLength.value,
columns: [columnEvent.data, ...columns.value],
rows: [columnEvent.data.key, ...rows.value],
doctype: "HD Ticket",
},
});
storage.value.columns = [columnEvent.data, ...columns.value];
storage.value.rows = [columnEvent.data.key, ...rows.value];
tickets.reload();
} else if (columnEvent.event === "remove") {
tickets.update({
params: {
order_by: sortsToApply,
filters: filtersToApply,
page_length: pageLength.value,
columns: columns.value.filter((column) => {
return column.key != columnEvent.data.key;
}),
rows: rows.value.filter((row) => {
return row != columnEvent.data.key;
}),
doctype: "HD Ticket",
},
});
storage.value.columns = columns.value.filter((column) => {
return column.key != columnEvent.data.key;
});
storage.value.rows = rows.value.filter((row) => {
return row != columnEvent.data.key;
});
tickets.reload();
} else if (columnEvent.event === "update") {
storage.value.columns = columnEvent.data;
}
}
function processSorts(sortEvent) {
if (sortEvent.event === "add") {
sorts.value.push(sortEvent.data);
Expand Down
Loading

0 comments on commit c625c47

Please sign in to comment.