Added a Select component to the Actions section of the Datatable, and API methods to load the available status-es from the Task doctype to populate the select for the tasks list.
This commit is contained in:
parent
adb7bc5930
commit
0c52f3fc23
4 changed files with 88 additions and 7 deletions
|
|
@ -13,6 +13,23 @@ def get_job_task_list(job_id=""):
|
||||||
return build_error_response(str(e), 500)
|
return build_error_response(str(e), 500)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_task_status_options():
|
||||||
|
print("DEBUG: Getting task status options")
|
||||||
|
try:
|
||||||
|
task_doctype = frappe.get_doc("DocType", "Task")
|
||||||
|
status_index = 0
|
||||||
|
for i, field in enumerate(task_doctype.fields):
|
||||||
|
if field.fieldname == "status":
|
||||||
|
status_index = i
|
||||||
|
break
|
||||||
|
options = task_doctype.fields[status_index].options.split()
|
||||||
|
print("DEBUG: Task Status options retreived", options)
|
||||||
|
return build_success_response(options)
|
||||||
|
except Exception as e:
|
||||||
|
return build_error_response(str(e), 500)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_tasks_table_data(filters={}, sortings=[], page=1, page_size=10):
|
def get_tasks_table_data(filters={}, sortings=[], page=1, page_size=10):
|
||||||
"""Get paginated task table data with filtering and sorting support."""
|
"""Get paginated task table data with filtering and sorting support."""
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ const FRAPPE_GET_INSTALL_PROJECTS_METHOD = "custom_ui.api.db.jobs.get_install_pr
|
||||||
const FRAPPE_GET_JOB_TEMPLATES_METHOD = "custom_ui.api.db.jobs.get_job_templates";
|
const FRAPPE_GET_JOB_TEMPLATES_METHOD = "custom_ui.api.db.jobs.get_job_templates";
|
||||||
// Task methods
|
// Task methods
|
||||||
const FRAPPE_GET_TASKS_METHOD = "custom_ui.api.db.tasks.get_tasks_table_data";
|
const FRAPPE_GET_TASKS_METHOD = "custom_ui.api.db.tasks.get_tasks_table_data";
|
||||||
|
const FRAPPE_GET_TASKS_STATUS_OPTIONS = "custom_ui.api.db.tasks.get_task_status_options";
|
||||||
// Invoice methods
|
// Invoice methods
|
||||||
const FRAPPE_GET_INVOICES_METHOD = "custom_ui.api.db.invoices.get_invoice_table_data";
|
const FRAPPE_GET_INVOICES_METHOD = "custom_ui.api.db.invoices.get_invoice_table_data";
|
||||||
const FRAPPE_UPSERT_INVOICE_METHOD = "custom_ui.api.db.invoices.upsert_invoice";
|
const FRAPPE_UPSERT_INVOICE_METHOD = "custom_ui.api.db.invoices.upsert_invoice";
|
||||||
|
|
@ -384,6 +385,12 @@ class Api {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async getTaskStatusOptions() {
|
||||||
|
console.log("DEBUG: API - Loading Task Status options form the backend.");
|
||||||
|
const result = await this.request(FRAPPE_GET_TASKS_STATUS_OPTIONS, {});
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// INVOICE / PAYMENT METHODS
|
// INVOICE / PAYMENT METHODS
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
|
||||||
|
|
@ -376,6 +376,18 @@
|
||||||
/>
|
/>
|
||||||
<!-- Dropdown menu would go here - could be implemented with PrimeVue Menu component -->
|
<!-- Dropdown menu would go here - could be implemented with PrimeVue Menu component -->
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Select menu for a single action with multiple options -->
|
||||||
|
<div
|
||||||
|
v-if="rowActionsGrouped.select.length > 0"
|
||||||
|
class="dt-row-actions-select"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
v-for="action in rowActionsGrouped.select"
|
||||||
|
:options="action.statusOptions"
|
||||||
|
:placeholder="action.label"
|
||||||
|
@change="handleSelectChange(action, slotProps.data, $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
</Column>
|
||||||
|
|
@ -387,6 +399,7 @@ import DataTable from "primevue/datatable";
|
||||||
import Column from "primevue/column";
|
import Column from "primevue/column";
|
||||||
import Tag from "primevue/tag";
|
import Tag from "primevue/tag";
|
||||||
import Button from "primevue/button";
|
import Button from "primevue/button";
|
||||||
|
import Select from "primevue/select";
|
||||||
import InputText from "primevue/inputtext";
|
import InputText from "primevue/inputtext";
|
||||||
import { FilterMatchMode } from "@primevue/core";
|
import { FilterMatchMode } from "@primevue/core";
|
||||||
import { useFiltersStore } from "../../stores/filters";
|
import { useFiltersStore } from "../../stores/filters";
|
||||||
|
|
@ -701,6 +714,7 @@ const rowActionsGrouped = computed(() => {
|
||||||
),
|
),
|
||||||
secondary: rowActions.value.filter((action) => action.layout?.priority === "secondary"),
|
secondary: rowActions.value.filter((action) => action.layout?.priority === "secondary"),
|
||||||
dropdown: rowActions.value.filter((action) => action.layout?.priority === "dropdown"),
|
dropdown: rowActions.value.filter((action) => action.layout?.priority === "dropdown"),
|
||||||
|
select: rowActions.value.filter((action) => action.layout?.priority === "select"),
|
||||||
};
|
};
|
||||||
return groups;
|
return groups;
|
||||||
});
|
});
|
||||||
|
|
@ -1018,6 +1032,22 @@ const handleActionClick = (action, rowData = null) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSelectChange = (action, rowData, event) => {
|
||||||
|
try {
|
||||||
|
if (typeof action.action === "function") {
|
||||||
|
if (rowData) {
|
||||||
|
// Row-specific action - pass row data
|
||||||
|
action.action(rowData, event.value);
|
||||||
|
} else {
|
||||||
|
// Global action - no row data needed
|
||||||
|
action.action();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error executing action:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleGlobalAction = (action) => {
|
const handleGlobalAction = (action) => {
|
||||||
handleActionClick(action);
|
handleActionClick(action);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ const notifications = useNotificationStore();
|
||||||
const tableData = ref([]);
|
const tableData = ref([]);
|
||||||
const totalRecords = ref(0);
|
const totalRecords = ref(0);
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
const showCompleted = ref(false);
|
||||||
|
const statusOptions = ref([]);
|
||||||
|
|
||||||
// Computed property to get current filters for the chart
|
// Computed property to get current filters for the chart
|
||||||
const currentFilters = computed(() => {
|
const currentFilters = computed(() => {
|
||||||
|
|
@ -63,6 +65,29 @@ const filterBy = (filter) => {
|
||||||
console.log("DEBUG: Tasks filterBy not implemented yet.");
|
console.log("DEBUG: Tasks filterBy not implemented yet.");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tableActions = [
|
||||||
|
{
|
||||||
|
label: "Show Completed",
|
||||||
|
action: () => {
|
||||||
|
showCompleted = !showCompleted
|
||||||
|
},
|
||||||
|
type: "button",
|
||||||
|
style: "info",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Set Status",
|
||||||
|
action: (rowData, newValue) => {
|
||||||
|
console.log("DEBUG: Row Data:", rowData);
|
||||||
|
console.log("DEBUG: New Value:", newValue);
|
||||||
|
},
|
||||||
|
rowAction: true,
|
||||||
|
layout: {
|
||||||
|
priority: "select"
|
||||||
|
},
|
||||||
|
statusOptions: statusOptions.value
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// Handle lazy loading events from DataTable
|
// Handle lazy loading events from DataTable
|
||||||
const handleLazyLoad = async (event) => {
|
const handleLazyLoad = async (event) => {
|
||||||
console.log("Tasks page - handling lazy load:", event);
|
console.log("Tasks page - handling lazy load:", event);
|
||||||
|
|
@ -154,13 +179,11 @@ const handlePropertyClick = (link, rowData) => {
|
||||||
// router.push(`/task?taskId=${rowData.name}`);
|
// router.push(`/task?taskId=${rowData.name}`);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
watch(
|
watch(showCompleted, () => {
|
||||||
() => filtersStore.getTableFilters("clients"),
|
if (showCompleted) {
|
||||||
async () => {
|
// TODO: Logic for filtering on "Completed" goes here
|
||||||
await refreshStatusCounts();
|
}
|
||||||
},
|
});
|
||||||
{ deep: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
// Load initial data
|
// Load initial data
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|
@ -175,6 +198,10 @@ onMounted(async () => {
|
||||||
const initialFilters = filtersStore.getTableFilters("tasks");
|
const initialFilters = filtersStore.getTableFilters("tasks");
|
||||||
const initialSorting = filtersStore.getTableSorting("tasks");
|
const initialSorting = filtersStore.getTableSorting("tasks");
|
||||||
|
|
||||||
|
const optionsResult = await Api.getTaskStatusOptions();
|
||||||
|
statusOptions.value = optionsResult;
|
||||||
|
console.log("DEBUG: Loaded Status options: ", statusOptions.value)
|
||||||
|
|
||||||
await handleLazyLoad({
|
await handleLazyLoad({
|
||||||
page: initialPagination.page,
|
page: initialPagination.page,
|
||||||
rows: initialPagination.rows,
|
rows: initialPagination.rows,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue