Skip to content
Merged
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
170 changes: 133 additions & 37 deletions summary-viewer/Contributors.html
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,15 @@
// show details cards
function showDetails(type, id, name, detailsSectionId) {
const detailsSection = document.getElementById(detailsSectionId)
if (detailsSectionId === "member-details-section") {
const p = document.getElementById("member-placeholder")
if (p) p.style.display = "none"
}

if (detailsSectionId === "team-details-section") {
const p = document.getElementById("team-placeholder")
if (p) p.style.display = "none"
}

if (!detailsSection) {
console.error(`Details section with ID "${detailsSectionId}" not found.`)
Expand Down Expand Up @@ -780,10 +789,18 @@ <h2>${name} Details</h2>
// Count the unique members
const numberOfUniqueMembers = uniqueMemberNames.size
document.getElementById("stat-number-1").textContent = numberOfUniqueMembers
const memberPlaceholder = document.getElementById("member-placeholder")
if (memberPlaceholder) {
memberPlaceholder.style.display = numberOfUniqueMembers > 0 ? "block" : "none"
}

const uniqueTeamNames = new Set(teamsDataArray.map((team) => team.name))
const numberOfUniqueTeams = teamsWithTaskData.size
document.getElementById("stat-number-2").textContent = numberOfUniqueTeams
const teamPlaceholder = document.getElementById("team-placeholder")
if (teamPlaceholder) {
teamPlaceholder.style.display = numberOfUniqueTeams > 0 ? "block" : "none"
}

// Extract all roles from project members
const memberRoles = jsonData.projectMembers.flatMap((member) => member.roles)
Expand Down Expand Up @@ -870,7 +887,16 @@ <h2>${name} Details</h2>
}

// Render the donut chart
Plotly.newPlot("roles-donut-chart", roleData, roleLayout)
const hasAnyRoles = roleValues.some((v) => v > 0)

if (hasAnyRoles) {
Plotly.newPlot("roles-donut-chart", roleData, roleLayout)
} else {
const rolesEl = document.getElementById("roles-donut-chart")
if (rolesEl) {
rolesEl.innerHTML = '<p class="empty-note">No roles</p>'
}
}

// Count the total number of rows
const totalTasks = latestTaskLogs.length
Expand Down Expand Up @@ -920,7 +946,12 @@ <h2>${name} Details</h2>
}

// Render the chart
Plotly.newPlot("completed-tasks-chart", dataCompletedTasks, layout)
if (totalTasks > 0) {
Plotly.newPlot("completed-tasks-chart", dataCompletedTasks, layout)
} else {
const el = document.getElementById("completed-tasks-chart")
if (el) el.innerHTML = '<p class="empty-note">No tasks yet</p>'
}

// completed form chart
// Count the total number of form tasks
Expand Down Expand Up @@ -972,7 +1003,12 @@ <h2>${name} Details</h2>
}

// Render the chart
Plotly.newPlot("completed-forms-chart", dataCompletedForms, layoutForm)
if (totalForms > 0) {
Plotly.newPlot("completed-forms-chart", dataCompletedForms, layoutForm)
} else {
const el = document.getElementById("completed-forms-chart")
if (el) el.innerHTML = '<p class="empty-note">No forms</p>'
}

//get roles individuals
const rolesByIndividual = projectMembersDataFrame.map((individual) => {
Expand Down Expand Up @@ -1042,6 +1078,12 @@ <h2>${name} Details</h2>
100
).toFixed(1)

// Hide progress bar if percentage is NaN
const showTasksBar = Number.isFinite(Number(tasksPercentComplete))
const showFormsBar = Number.isFinite(Number(formsPercentComplete))
const showNoTasksNote = !showTasksBar
const showNoFormsNote = !showFormsBar

// Create the card container
const card = document.createElement("div")
card.className = "small-card clickable"
Expand All @@ -1051,28 +1093,57 @@ <h2>${name} Details</h2>
title.textContent = member.name
card.appendChild(title)

// Create a container for the donut chart
const containerId = `member-role-chart-${member.projectMemberId}`
const chartDiv = document.createElement("div")
chartDiv.id = containerId
card.appendChild(chartDiv)
// Create a container for the donut chart or an empty note
const hasRoles = member.roles.length > 0

let chartDiv = null
if (hasRoles) {
chartDiv = document.createElement("div")
chartDiv.id = `member-role-chart-${member.projectMemberId}`
card.appendChild(chartDiv)
} else {
const note = document.createElement("p")
note.className = "empty-note"
note.textContent = "No roles"
card.appendChild(note)
}

// Add progress bars for tasks and forms
const progressBars = `
<div class="progress-container">
<div class="progress-bar" style="width: ${tasksPercentComplete}%; background-color: ${themeColors.primary3};" title="Tasks: ${tasksPercentComplete}% Completed"></div>
</div>
<div class="progress-container">
<div class="progress-bar" style="width: ${formsPercentComplete}%; background-color: ${themeColors.primary4};" title="Forms: ${formsPercentComplete}% Submitted"></div>
</div>
`
${
showTasksBar
? `
<div class="progress-container">
<div class="progress-bar"
style="width: ${tasksPercentComplete}%; background-color: ${themeColors.primary3};"
title="Tasks: ${tasksPercentComplete}% Completed"></div>
</div>`
: `<p class="empty-note">No tasks</p>`
}
${
showFormsBar
? `
<div class="progress-container">
<div class="progress-bar"
style="width: ${formsPercentComplete}%; background-color: ${themeColors.primary4};"
title="Forms: ${formsPercentComplete}% Submitted"></div>
</div>`
: `<p class="empty-note">No forms</p>`
}
`
card.innerHTML += progressBars // Append progress bars to the card

// Append the card to the members section and render the chart
// Append the card to the members section and render the chart if appropriate
const memberRoleChartContainer = document.getElementById("members-section")
if (memberRoleChartContainer) {
memberRoleChartContainer.appendChild(card)
createDonutChart(data, containerId, `${member.name}`)
if (hasRoles) {
createDonutChart(
data,
`member-role-chart-${member.projectMemberId}`,
`${member.name}`
)
}
} else {
console.error("Main container for member charts not found!")
}
Expand Down Expand Up @@ -1157,32 +1228,57 @@ <h2>${name} Details</h2>
title.textContent = team.teamName
card.appendChild(title)

// Create a container for the donut chart
const containerId = `team-role-chart-${team.teamId}`
const chartDiv = document.createElement("div")
chartDiv.id = containerId
card.appendChild(chartDiv)
// Create a container for the donut chart or an empty note
const hasRoles = team.roles.length > 0

let chartDiv = null
if (hasRoles) {
chartDiv = document.createElement("div")
chartDiv.id = `team-role-chart-${team.teamId}`
card.appendChild(chartDiv)
} else {
const note = document.createElement("p")
note.className = "empty-note"
note.textContent = "No roles"
card.appendChild(note)
}

// NaN guards for progress bars
const showTeamTasksBar = Number.isFinite(Number(team.tasksPercentComplete))
const showTeamFormsBar = Number.isFinite(Number(team.formsPercentComplete))

// Add progress bars for tasks and forms
const progressBars = `
<div class="progress-container">
<div class="progress-bar"
style="width: ${team.tasksPercentComplete}%; background-color: ${themeColors.primary3};"
title="Tasks: ${team.tasksPercentComplete}% Completed"></div>
</div>
<div class="progress-container">
<div class="progress-bar"
style="width: ${team.formsPercentComplete}%; background-color: ${themeColors.primary4};"
title="Forms: ${team.formsPercentComplete}% Submitted"></div>
</div>
`
${
showTeamTasksBar
? `
<div class="progress-container">
<div class="progress-bar"
style="width: ${team.tasksPercentComplete}%; background-color: ${themeColors.primary3};"
title="Tasks: ${team.tasksPercentComplete}% Completed"></div>
</div>`
: `<p class="empty-note">No tasks</p>`
}
${
showTeamFormsBar
? `
<div class="progress-container">
<div class="progress-bar"
style="width: ${team.formsPercentComplete}%; background-color: ${themeColors.primary4};"
title="Forms: ${team.formsPercentComplete}% Submitted"></div>
</div>`
: `<p class="empty-note">No forms</p>`
}
`
card.innerHTML += progressBars // Append progress bars to the card

// Append the card to the teams section and render the chart
// Append the card to the teams section and render the chart if appropriate
const teamRoleChartContainer = document.getElementById("teams-section")
if (teamRoleChartContainer) {
teamRoleChartContainer.appendChild(card)
createDonutChart(data, containerId, `${team.teamName}`)
if (hasRoles) {
createDonutChart(data, `team-role-chart-${team.teamId}`, `${team.teamName}`)
}
} else {
console.error("Main container for team charts not found!")
}
Expand Down Expand Up @@ -1625,7 +1721,7 @@ <h3>Forms Submitted</h3>
</p>
<div id="members-section"></div>
<div id="member-details-section" class="details-container">
<p>Select a card to view details about the contributor or team.</p>
<p id="member-placeholder">Select a card to view details about the contributor.</p>
</div>
</div>
</div>
Expand All @@ -1643,7 +1739,7 @@ <h3>Forms Submitted</h3>
</p>
<div id="teams-section"></div>
<div id="team-details-section" class="details-container">
<p>Select a card to view details about the contributor or team.</p>
<p id="team-placeholder">Select a card to view details about the team.</p>
</div>
</div>
</div>
Expand Down
10 changes: 8 additions & 2 deletions summary-viewer/Events.html
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ <h3>Select Time Interval and Color Scheme</h3>
const tickvals = []
const ticktext = []
const allChartData = []
let rowCount = 0

milestoneDataRaw.forEach((m) => {
const milestoneId = String(m.id)
Expand All @@ -489,6 +490,7 @@ <h3>Select Time Interval and Color Scheme</h3>
)

milestoneTasks.forEach((t) => {
rowCount += 1
const yLabel = `task-${t.id}`
tickvals.push(yLabel)
ticktext.push("↳ " + t.name)
Expand All @@ -509,6 +511,7 @@ <h3>Select Time Interval and Color Scheme</h3>
})
})

rowCount += 1
tickvals.push(milestoneId)
ticktext.push(m.name)

Expand Down Expand Up @@ -543,8 +546,9 @@ <h3>Select Time Interval and Color Scheme</h3>
type: "category",
automargin: true,
tickfont: { size: 14 },
tickpadding: 8,
},
height: milestoneDataRaw.length * 40 + 100,
height: Math.min(rowCount * 40 + 120, 2000),
showlegend: false,
margin: { l: 150, r: 30, t: 50, b: 40 },
}
Expand Down Expand Up @@ -740,7 +744,9 @@ <h1>Milestone Gantt Chart</h1>
<i class="expand-icon">+</i>
</label>
<div class="collapse-content">
<div id="milestone-gantt-container"></div>
<div class="gantt-scroll-container">
<div id="milestone-gantt-container"></div>
</div>
</div>
</div>
<div class="custom-collapse">
Expand Down
6 changes: 0 additions & 6 deletions summary-viewer/Form_Data.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,6 @@
<link rel="stylesheet" href="./_file/style.ef1f7908.css" />

<script type="module">
// Load Plot and d3 (if needed elsewhere)
const [Plot, d3] = await Promise.all([
import("https://cdn.jsdelivr.net/npm/@observablehq/plot@0.6.17/+esm"),
import("https://cdn.jsdelivr.net/npm/d3@7/+esm"),
])

// Embed the JSON data directly here
const jsonData = __INJECT_JSON__
document.addEventListener("DOMContentLoaded", () => {
Expand Down
40 changes: 28 additions & 12 deletions summary-viewer/Tasks.html
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,7 @@
// Convert taskLogStatus to a user-friendly format
const formattedStatus = task.taskLogStatus === "COMPLETED" ? "Completed" : "Not Completed"

const formattedTaskStatus =
task.taskStatus === "COMPLETED" ? "Completed" : "Not Completed"
const formattedTaskStatus = task.status === "COMPLETED" ? "Completed" : "Not Completed"

// Return a new object with updated values
return {
Expand Down Expand Up @@ -316,8 +315,13 @@
paper_bgcolor: "rgba(0, 0, 0, 0)", // Transparent chart area background
}

// Render the chart
Plotly.newPlot("completed-tasks-chart", dataCompletedTasks, layoutCompletedTasks)
// Render the chart (only if there are tasks)
if (totalTasks > 0) {
Plotly.newPlot("completed-tasks-chart", dataCompletedTasks, layoutCompletedTasks)
} else {
const el = document.getElementById("completed-tasks-chart")
if (el) el.innerHTML = '<p class="empty-note">No tasks created yet</p>'
}

const latestTaskLogs = Array.from(
tasksDataFrame
Expand Down Expand Up @@ -385,8 +389,13 @@
paper_bgcolor: "rgba(0, 0, 0, 0)", // Transparent chart area background
}

// Render the chart
Plotly.newPlot("completed-tasklogs-chart", dataCompletedTaskLogs, layout)
// Render the chart (only if there are task logs)
if (totalTaskLogs > 0) {
Plotly.newPlot("completed-tasklogs-chart", dataCompletedTaskLogs, layout)
} else {
const el = document.getElementById("completed-tasklogs-chart")
if (el) el.innerHTML = '<p class="empty-note">No task logs yet</p>'
}

// Step 1: Group logs by taskId and assignedToId
const taskLogMap = tasksDataFrame.reduce((map, log) => {
Expand Down Expand Up @@ -431,11 +440,18 @@
})

// Step 3: Calculate average completion time
const averageCompletionTime =
completedCount > 0
? `${(totalCompletionTime / completedCount).toFixed(2)} Days`
: "0 days"
document.getElementById("stat-number-3").textContent = averageCompletionTime
const statNumEl = document.getElementById("stat-number-3")
const statIconEl = document.getElementById("stat-icon-3")

if (completedCount > 0) {
const averageCompletionTime = `${(totalCompletionTime / completedCount).toFixed(2)} Days`
if (statNumEl) statNumEl.textContent = averageCompletionTime
if (statIconEl) statIconEl.style.display = ""
} else {
if (statNumEl)
statNumEl.innerHTML = '<span class="empty-note">No completed tasks yet</span>'
if (statIconEl) statIconEl.style.display = "none"
}

function createTaskDropdownAndDataTable(containerId, dataTableContainerId) {
// Step 1: Get unique task names
Expand Down Expand Up @@ -683,7 +699,7 @@ <h4>Task Logs Completed</h4>
<div class="stat-card">
<h4>Average Completion Time</h4>
<p id="stat-number-3">Days</p>
<i class="fas fa-clock" id="stat-number-3" aria-hidden="true"></i>
<i class="fas fa-clock" id="stat-icon-3" aria-hidden="true"></i>
</div>
</div>
</div>
Expand Down
Loading