<script>
// Global variables
var ArrWorkStationProductTaskMappingList = [];
var ArrTechncinList = [];
var scheduler;
var currentEditingEvent = null;
var localEvents = [];
var nextId = 1;
// Sample data for demonstration
var sampleWorkStationData = [
{ WorkStationID: "WS001", WorkStationName: "Wall 1", ProdCode: "PROD001", TaskID: "T001", TaskName: "Task 1", Duration: 2.5 },
{ WorkStationID: "WS002", WorkStationName: "Wall 2", ProdCode: "PROD002", TaskID: "T002", TaskName: "Task 2", Duration: 3.0 },
{ WorkStationID: "WS003", WorkStationName: "Floor (B)", ProdCode: "PROD003", TaskID: "T003", TaskName: "Task 3", Duration: 1.5 },
{ WorkStationID: "WS004", WorkStationName: "Black Front", ProdCode: "PROD004", TaskID: "T004", TaskName: "Task 4", Duration: 1.5 },
{ WorkStationID: "WS004", WorkStationName: "Floor (Light 1)", ProdCode: "PROD005", TaskID: "T005", TaskName: "Task 5", Duration: 1.5 }
];
var sampleTechnicianData = [
{ TechnicianName: "John Doe", TechnicianUserID: "USER001", TechnicianMail: "john@example.com" },
{ TechnicianName: "Jane Smith", TechnicianUserID: "USER002", TechnicianMail: "jane@example.com" },
{ TechnicianName: "Bob Johnson", TechnicianUserID: "USER003", TechnicianMail: "bob@example.com" }
];
// Initialize sample data
ArrWorkStationProductTaskMappingList = sampleWorkStationData;
ArrTechncinList = sampleTechnicianData;
// Initialize sample events
localEvents = [
{
ScheduleID: 1,
Status: "Active",
ScheduleBatchID: "BATCH001",
ResourceID: "WS001",
ResourceName: "Wall 1",
ResourceMappedForID: "T001",
ResourceMappedForName: "Task 1",
JobNo: "JOB001",
ProdCode: "PROD001",
JobDetailUniqueID: "JD001",
Prod_Name: "Product 1",
ScheduleCode: "SCH001",
FromDate: "2025/7/15",
ToDate: "2025/7/15",
FromTime: "09:00",
ToTime: "11:00",
title: "Workstation Task - Product 1",
IsAllDayEvent: false,
description: "Sample workstation task for Product 1",
TypeID: 1,
start: new Date("2025/7/15 09:00"),
end: new Date("2025/7/15 11:00"),
resource: "WS001",
resourceType: 1
},
{
ScheduleID: 2,
Status: "Active",
ScheduleBatchID: "BATCH002",
ResourceID: "USER001",
ResourceName: "John Doe",
ResourceMappedForID: "S001",
ResourceMappedForName: "Sample 1",
JobNo: "JOB001",
ProdCode: "PROD001",
JobDetailUniqueID: "JD002",
Prod_Name: "Product 1",
ScheduleCode: "SCH002",
FromDate: "2025/7/15",
ToDate: "2025/7/15",
FromTime: "10:00",
ToTime: "12:00",
title: "Technician Task - John Doe",
IsAllDayEvent: false,
description: "Sample technician task",
TypeID: 2,
start: new Date("2025/7/15 10:00"),
end: new Date("2025/7/15 12:00"),
resource: "USER001",
resourceType: 2
},
{
ScheduleID: 3,
Status: "Active",
ScheduleBatchID: "BATCH003",
ResourceID: "WS002",
ResourceName: "Wall 2",
ResourceMappedForID: "T002",
ResourceMappedForName: "Task 2",
JobNo: "JOB002",
ProdCode: "PROD002",
JobDetailUniqueID: "JD003",
Prod_Name: "Product 2",
ScheduleCode: "SCH003",
FromDate: "2025/7/15",
ToDate: "2025/7/15",
FromTime: "13:00",
ToTime: "15:00",
title: "Workstation Task - Product 2",
IsAllDayEvent: false,
description: "Another workstation task for Product 2",
TypeID: 1,
start: new Date("2025/7/15 13:00"),
end: new Date("2025/7/15 15:00"),
resource: "WS002",
resourceType: 1
}
];
$(document).ready(function () {
// Initialize controls
$("#ddlViewType").val($("#hdViewType").val());
$("#txtProductCodes").val($("#hdcurrentTestCodeToAllocate").val());
// Initialize scheduler
initializeScheduler();
populateResourceDropdown();
// Event handlers
$("#btnRefreshScheduler").click(function () {
$("#hdViewType").val($("#ddlViewType").val());
$("#hdcurrentTestCodeToAllocate").val($("#txtProductCodes").val());
refreshScheduler();
});
$("#btnSaveSchedule").click(saveScheduleEvent);
});
// Add this function to validate and fix event resourceType values
function validateAndFixEvents() {
console.log("Validating events...");
localEvents.forEach(function (event, index) {
var correctResourceType = null;
// Check if it's a workstation resource
var workstationData = getFilteredWorkstationData();
var isWorkstation = workstationData.some(function (ws) {
return ws.WorkStationID === event.ResourceID;
});
if (isWorkstation) {
correctResourceType = 1;
} else {
// Check if it's a technician resource
var isTechnician = ArrTechncinList.some(function (tech) {
return tech.TechnicianUserID === event.ResourceID;
});
if (isTechnician) {
correctResourceType = 2;
}
}
if (correctResourceType && event.resourceType !== correctResourceType) {
console.log("Fixing event " + index + " resourceType from " + event.resourceType + " to " + correctResourceType);
event.resourceType = correctResourceType;
event.resource = event.ResourceID; // Make sure resource field matches ResourceID
}
});
console.log("Events after validation:", localEvents);
}
function initializeScheduler() {
validateAndFixEvents();
var resources = buildResourcesArray();
var dataSource = buildDataSource();
if (scheduler && typeof scheduler.destroy === "function") {
scheduler.destroy();
$("#scheduler").empty(); // Optional
}
scheduler = $("#scheduler").kendoScheduler({
date: new Date("2025/7/15"),
startTime: new Date("2025/7/15 08:00"),
endTime: new Date("2025/7/15 18:00"),
height: 800,
eventHeight: 50,
majorTick: 60,
views: [
"day",
"week",
"month",
{
type: "timeline",
selected: true,
startTime: new Date("2025/7/15 08:00"),
endTime: new Date("2025/7/15 18:00"),
workDayStart: new Date("2025/7/15 08:00"),
workDayEnd: new Date("2025/7/15 18:00"),
majorTick: 60,
minorTickCount: 2,
showWorkHours: true
},
{
type: "timelineWeek",
startTime: new Date("2025/7/15 08:00"),
endTime: new Date("2025/7/15 18:00"),
workDayStart: new Date("2025/7/15 08:00"),
workDayEnd: new Date("2025/7/15 18:00"),
majorTick: 60,
minorTickCount: 2,
showWorkHours: true
}
],
timezone: "Etc/UTC",
dataSource: dataSource,
resources: resources,
group: {
resources: ["resourceType", "resource"],
orientation: "vertical"
},
/*eventTemplate: $("#event-template").html(),*/
add: function (e) {
e.preventDefault();
openScheduleModal(null, e.event);
},
edit: function (e) {
e.preventDefault();
openScheduleModal(e.event, null);
},
remove: function (e) {
if (confirm("Are you sure you want to delete this event?")) {
console.log("Deleting event:", e.event);
// The scheduler will handle the delete automatically
} else {
e.preventDefault();
}
},
dataBound: function (e) {
// Add tooltips
$(".k-event").each(function () {
var uid = $(this).attr("data-uid");
var event = scheduler.dataSource.getByUid(uid);
//if (event) {
// $(this).attr("title", buildTooltipContent(event));
//}
});
}
}).data("kendoScheduler");
}
function buildResourcesArray() {
var resources = [];
var viewType = $("#hdViewType").val();
console.log("Building resources for view type:", viewType);
// Build the resource type grouping first
var resourceTypeData = [];
if (viewType === "B" || viewType === "W") {
resourceTypeData.push({
text: "Workstation",
value: 1,
color: "#2572c0"
});
}
if (viewType === "B" || viewType === "T") {
resourceTypeData.push({
text: "Technician",
value: 2,
color: "#f8a398"
});
}
// Add resourceType as the first resource for grouping
resources.push({
field: "resourceType",
name: "resourceType",
title: "Resource Type",
dataSource: resourceTypeData
});
// Build individual resources with correct resourceType values
var allResources = [];
// Add workstations
if (viewType === "B" || viewType === "W") {
var workstationData = getFilteredWorkstationData();
console.log("Adding workstations:", workstationData);
workstationData.forEach(function (item) {
allResources.push({
text: item.WorkStationName,
value: item.WorkStationID,
color: "#2572c0",
resourceType: 1 // CRITICAL: This must match the resourceType value above
});
});
}
// Add technicians
if (viewType === "B" || viewType === "T") {
console.log("Adding technicians:", ArrTechncinList);
ArrTechncinList.forEach(function (item) {
allResources.push({
text: item.TechnicianName,
value: item.TechnicianUserID,
color: "#f8a398",
resourceType: 2 // CRITICAL: This must match the resourceType value above
});
});
}
// Add the individual resources
resources.push({
field: "resource",
name: "resource",
title: "Resource",
valuePrimitive: true,
dataSource: allResources,
group: "resourceType" // This tells Kendo to group by resourceType
});
console.log("Final resources array:", resources);
console.log("All individual resources:", allResources);
return resources;
}
function getFilteredWorkstationData() {
var productCodes = $("#hdcurrentTestCodeToAllocate").val();
var filteredData = ArrWorkStationProductTaskMappingList;
if (productCodes && productCodes.trim() !== "") {
var codes = productCodes.split(',').map(function (code) {
return code.trim();
});
filteredData = ArrWorkStationProductTaskMappingList.filter(function (item) {
return codes.indexOf(item.ProdCode) !== -1;
});
}
// Get distinct workstations
var distinctWorkstations = [];
var seen = {};
filteredData.forEach(function (item) {
var key = item.WorkStationID; // + "_" + item.TaskID;
if (!seen[key]) {
seen[key] = true;
distinctWorkstations.push(item);
}
});
return distinctWorkstations;
}
function buildDataSource() {
return new kendo.data.SchedulerDataSource({
batch: true,
transport: {
read: function (options) {
try {
options.success(localEvents);
} catch (error) {
console.error('Error reading events:', error);
options.error(error);
}
},
create: function (options) {
try {
var newEvents = options.data.models || [options.data];
newEvents.forEach(function (event) {
event.ScheduleID = nextId++;
localEvents.push(event);
});
options.success(newEvents);
} catch (error) {
console.error('Error creating events:', error);
options.error(error);
}
},
update: function (options) {
try {
var updatedEvents = options.data.models || [options.data];
updatedEvents.forEach(function (updatedEvent) {
var index = localEvents.findIndex(function (e) {
return e.ScheduleID === updatedEvent.ScheduleID;
});
if (index !== -1) {
localEvents[index] = updatedEvent;
}
});
options.success(updatedEvents);
} catch (error) {
console.error('Error updating events:', error);
options.error(error);
}
},
destroy: function (options) {
try {
var deletedEvents = options.data.models || [options.data];
deletedEvents.forEach(function (deletedEvent) {
var index = localEvents.findIndex(function (e) {
return e.ScheduleID === deletedEvent.ScheduleID;
});
if (index !== -1) {
localEvents.splice(index, 1);
}
});
options.success(deletedEvents);
} catch (error) {
console.error('Error deleting events:', error);
options.error(error);
}
}
},
schema: {
model: {
id: "ScheduleID",
fields: {
ScheduleID: { type: "number" },
title: { from: "title", defaultValue: "No title", validation: { required: true } },
start: { type: "date", validation: { required: true } },
end: { type: "date", validation: { required: true } },
resource: { nullable: true },
resourceType: { nullable: true },
isAllDay: { type: "boolean", from: "IsAllDayEvent", defaultValue: false },
description: { type: "string" },
Status: { type: "string" },
ScheduleBatchID: { type: "string" },
ResourceID: { type: "string" },
ResourceName: { type: "string" },
ResourceMappedForID: { type: "string" },
ResourceMappedForName: { type: "string" },
JobNo: { type: "string" },
ProdCode: { type: "string" },
JobDetailUniqueID: { type: "string" },
Prod_Name: { type: "string" },
ScheduleCode: { type: "string" },
FromDate: { type: "string" },
ToDate: { type: "string" },
FromTime: { type: "string" },
ToTime: { type: "string" },
TypeID: { type: "number" }
}
}
}
});
}
function refreshScheduler() {
initializeScheduler();
populateResourceDropdown();
}
function openScheduleModal(event, newEvent) {
currentEditingEvent = event;
// Populate resource dropdown
populateResourceDropdown();
if (event) {
// Edit mode
$("#modalTitle").text("Edit Schedule Event");
$("#eventId").val(event.ScheduleID);
$("#eventTitle").val(event.title);
$("#eventStart").val(formatDateTimeLocal(event.start));
$("#eventEnd").val(formatDateTimeLocal(event.end));
$("#eventResource").val(event.ResourceID);
$("#eventDescription").val(event.description || "");
$("#eventTypeId").val(event.TypeID);
$("#eventResourceId").val(event.ResourceID);
} else {
// Add mode
$("#modalTitle").text("Add Schedule Event");
$("#eventId").val("");
$("#eventTitle").val("");
$("#eventStart").val(formatDateTimeLocal(newEvent.start));
$("#eventEnd").val(formatDateTimeLocal(newEvent.end));
$("#eventResource").val("");
$("#eventDescription").val("");
$("#eventTypeId").val("");
$("#eventResourceId").val("");
}
$('#scheduleModal').modal('show');
}
function populateResourceDropdown() {
var dropdown = $("#eventResource");
dropdown.empty();
dropdown.append('<option value="">Select Resource</option>');
var resources = buildResourcesArray();
if (resources.length > 1) {
var groupedResources = {
Workstations: [],
Technicians: []
};
resources[1].dataSource.forEach(function (item) {
if (item.resourceType === 1) {
groupedResources.Workstations.push(item);
} else if (item.resourceType === 2) {
groupedResources.Technicians.push(item);
}
});
// Append Workstations
if (groupedResources.Workstations.length > 0) {
var wsGroup = $('<optgroup label="Workstations"></optgroup>');
groupedResources.Workstations.forEach(function (ws) {
wsGroup.append('<option value="' + ws.value + '">' + ws.text + '</option>');
});
dropdown.append(wsGroup);
}
// Append Technicians
if (groupedResources.Technicians.length > 0) {
var techGroup = $('<optgroup label="Technicians"></optgroup>');
groupedResources.Technicians.forEach(function (tech) {
techGroup.append('<option value="' + tech.value + '">' + tech.text + '</option>');
});
dropdown.append(techGroup);
}
}
}
function saveScheduleEvent() {
//if (!$("#scheduleForm")[0].checkValidity()) {
// $("#scheduleForm")[0].reportValidity();
// return;
//}
var startDate = new Date($("#eventStart").val());
var endDate = new Date($("#eventEnd").val());
var selectedResource = $("#eventResource").val();
// Determine TypeID based on selected resource
var typeId = 1; // default to workstation
var resourceName = "";
var resourceMappedForID = "";
var resourceMappedForName = "";
// Find the selected resource details
var resources = buildResourcesArray();
var resourceData = resources[1].dataSource.find(function (r) { return r.value === selectedResource; });
if (resourceData) {
typeId = resourceData.resourceType;
resourceName = resourceData.text;
if (typeId === 1) {
// Workstation
resourceMappedForID = resourceData.taskId;
resourceMappedForName = resourceData.taskName;
} else {
// Technician
resourceMappedForID = resourceData.technicianUserId;
resourceMappedForName = resourceData.text;
}
}
var eventData = {
ScheduleID: $("#eventId").val() || nextId++,
Status: "Active",
ScheduleBatchID: "BATCH" + new Date().getTime(),
ResourceID: selectedResource,
ResourceName: resourceName,
ResourceMappedForID: resourceMappedForID,
ResourceMappedForName: resourceMappedForName,
JobNo: $("#hdJobNo").val(),
ProdCode: $("#hdcurrentTestCodeToAllocate").val().split(',')[0] || "",
JobDetailUniqueID: $("#hdSelectedJobIDs").val().split(',')[0] || "",
Prod_Name: "Product Name",
ScheduleCode: "SCH" + new Date().getTime(),
FromDate: kendo.toString(startDate, "yyyy/M/d"),
ToDate: kendo.toString(endDate, "yyyy/M/d"),
FromTime: kendo.toString(startDate, "HH:mm"),
ToTime: kendo.toString(endDate, "HH:mm"),
title: $("#eventTitle").val(),
IsAllDayEvent: false,
description: $("#eventDescription").val(),
TypeID: typeId,
start: startDate,
end: endDate,
resource: selectedResource,
resourceType: typeId
};
if (currentEditingEvent) {
// Update existing event
var existingEvent = scheduler.dataSource.get(currentEditingEvent.ScheduleID);
for (var key in eventData) {
existingEvent.set(key, eventData[key]);
}
} else {
// Add new event
scheduler.dataSource.add(eventData);
}
$('#scheduleModal').modal('hide');
}
function formatDateTimeLocal(date) {
var d = new Date(date);
var month = ('0' + (d.getMonth() + 1)).slice(-2);
var day = ('0' + d.getDate()).slice(-2);
var hours = ('0' + d.getHours()).slice(-2);
var minutes = ('0' + d.getMinutes()).slice(-2);
return d.getFullYear() + '-' + month + '-' + day + 'T' + hours + ':' + minutes;
}
</script>
<input type="hidden" id="hdViewType" value="B" />
<input type="hidden" id="hdcurrentTestCodeToAllocate" value="PROD001,PROD002,PROD003,PROD004,PROD005" />
<input type="hidden" id="hdJobNo" value="JOB001" />
<input type="hidden" id="hdSelectedJobIDs" value="JD001,JD002" />
<div class="resource-controls">
<div class="row">
<div class="col-md-3">
<label for="ddlViewType">View Type:</label>
<select id="ddlViewType" class="form-control" style="height: 38px;">
<option value="B">Both (Workstation & Technician)</option>
<option value="W">Workstation Only</option>
<option value="T">Technician Only</option>
</select>
</div>
<div class="col-md-3" style="display:none">
<label for="txtProductCodes">Product Codes:</label>
<input type="text" id="txtProductCodes" class="form-control" placeholder="PROD001,PROD002,PROD003,PROD004,PROD005" />
</div>
<div class="col-md-3">
<button id="btnRefreshScheduler" class="btn btn-primary" style="margin-top: 25px;">Refresh Scheduler</button>
</div>
</div>
</div>
<div class="scheduler-container">
<div id="scheduler" style="width:100%"></div>
</div>
anyone please give me the solution for this