{"version":3,"file":"js/app.733d15d6.js","mappings":"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","sources":["webpack://python-webpack-boilerplate/./frontend/src/utils/hijack.js","webpack://python-webpack-boilerplate/./frontend/src/utils/sorttable.js","webpack://python-webpack-boilerplate/./frontend/src/utils/spark.js","webpack://python-webpack-boilerplate/./frontend/src/utils/image.js","webpack://python-webpack-boilerplate/./frontend/src/utils/timeForm.js","webpack://python-webpack-boilerplate/./frontend/src/context/UserContextProvider.js","webpack://python-webpack-boilerplate/./frontend/src/components/ErrorBoundary.js","webpack://python-webpack-boilerplate/./frontend/src/components/UserMenu.js","webpack://python-webpack-boilerplate/./frontend/src/components/Clock.js","webpack://python-webpack-boilerplate/./frontend/src/application/app.js","webpack://python-webpack-boilerplate/./frontend/src/dataComponents.js","webpack://python-webpack-boilerplate/./frontend/src/utils/selected.js","webpack://python-webpack-boilerplate/./frontend/src/utils/chart.js"],"sourcesContent":["var myModal = document.getElementById(\"hijackModal\");\nif (myModal) {\n  myModal.addEventListener(\"show.bs.modal\", function (event) {\n    var button = event.relatedTarget;\n    var userId = button.getAttribute(\"data-userid\");\n    var userName = button.getAttribute(\"data-username\");\n    var form = myModal.querySelector(\"#hijack-user\");\n    // Update form elements\n    form.querySelector('input[name=\"user_pk\"]').value = userId;\n\n    // Update modal body\n    var modalBody = myModal.querySelector(\".modal-body\");\n    modalBody.innerHTML = \"Hijack \" + userName + \"?\";\n  });\n}\n","// ==============================================================\n// |                  This code was generated                   |\n// |                   by ChatGPT, an OpenAI                    |\n// |                      language model.                       |\n// ==============================================================\n\nconst table = document.getElementById(\"table-select\");\nif (table) {\n  const tbody = table.getElementsByTagName(\"tbody\")[0];\n  const rows = Array.from(tbody.getElementsByTagName(\"tr\"));\n\n  const sortTable = (columnIndex, ascending) => {\n    const isNumeric = !isNaN(\n      rows[0].getElementsByTagName(\"td\")[columnIndex].textContent\n    );\n    rows.sort((row1, row2) => {\n      const cell1 = row1.getElementsByTagName(\"td\")[columnIndex].textContent;\n      const cell2 = row2.getElementsByTagName(\"td\")[columnIndex].textContent;\n      const value1 = isNumeric ? parseInt(cell1) : cell1.toLowerCase();\n      const value2 = isNumeric ? parseInt(cell2) : cell2.toLowerCase();\n      if (value1 < value2) return ascending ? -1 : 1;\n      if (value1 > value2) return ascending ? 1 : -1;\n      return 0;\n    });\n    rows.forEach((row) => tbody.appendChild(row));\n  };\n\n  const addHeaderListeners = () => {\n    const headers = table.getElementsByTagName(\"th\");\n    Array.from(headers).forEach((header, index) => {\n      if (!header.classList.contains(\"no-sort\")) {\n        header.addEventListener(\"click\", () => {\n          const isAscending = header.getAttribute(\"data-order\") === \"asc\";\n          sortTable(index, !isAscending);\n          header.setAttribute(\"data-order\", isAscending ? \"desc\" : \"asc\");\n        });\n      }\n    });\n  };\n  addHeaderListeners();\n}\n","// Via ChatGPT\nfunction createSparkline(containerId) {\n  // Get the container element\n  var container = document.getElementById(containerId);\n\n  // Get the canvas element\n  var canvas = container.querySelector(\"canvas\");\n\n  // Get the dataset and labels from data attributes\n  var dataset = JSON.parse(canvas.getAttribute(\"data-dataset\"));\n  var labels = JSON.parse(canvas.getAttribute(\"data-labels\"));\n\n  // Get the width, height, and color from style attribute\n  var width = parseInt(canvas.style.width, 10);\n  var height = parseInt(canvas.style.height, 10);\n  var color = canvas.style.color;\n\n  // Get the 2d rendering context of the canvas\n  var ctx = canvas.getContext(\"2d\");\n\n  // Calculate the scale for x and y axes\n  var scaleX = width / (labels.length - 1);\n  var scaleY = height / (Math.max(...dataset[0]) - Math.min(...dataset[0]));\n\n  // Draw the sparkline\n  ctx.beginPath();\n  ctx.moveTo(0, height - (dataset[0][0] - Math.min(...dataset[0])) * scaleY);\n  for (var i = 1; i < labels.length; i++) {\n    ctx.lineTo(\n      i * scaleX,\n      height - (dataset[0][i] - Math.min(...dataset[0])) * scaleY\n    );\n  }\n  ctx.strokeStyle = color;\n  ctx.lineWidth = 2;\n  ctx.stroke();\n}\n\ntry {\n  createSparkline(\"sparkline1Container\");\n  createSparkline(\"sparkline2Container\");\n  createSparkline(\"sparkline3Container\");\n} catch {\n  console.log(\"error\");\n}\ntry {\n  createSparkline(\"sparkline4Container\");\n  createSparkline(\"sparkline5Container\");\n  createSparkline(\"sparkline6Container\");\n  createSparkline(\"sparkline7Container\");\n} catch {\n  console.log(\"error\");\n}\n","// Select all image links with data-bs-toggle=\"modal\"\nconst imageLinks = document.querySelectorAll('[data-bs-toggle=\"modal\"]');\n\n// Select the modal's image element\nconst modalImage = document.getElementById('modalImage');\n\n// Iterate over each image link and attach a click event listener\nimageLinks.forEach(link => {\n   link.addEventListener('shown.bs.modal', function () {\n      // Get the source URL of the clicked image\n      const imageUrl = this.querySelector('img').src;\n\n      // Set the source URL for the modal's image element\n      modalImage.src = imageUrl;\n   });\n});\n","/**\n * Time form cascade: when invoice, project, or task dropdowns change,\n * update the other two dropdowns based on the data relationships.\n *\n * Relationships:\n *   Invoice → project (invoice.project), task (project.default_task)\n *   Project → task (project.default_task)\n *   Task    → project (task.project)\n *\n * Requires window.TIME_API_URLS to be set by the template (see edit.html).\n */\n\nfunction initTimeFormDropdowns() {\n  const invoiceSelect = document.getElementById('id_invoice');\n  const projectSelect = document.getElementById('id_project');\n  const taskSelect = document.getElementById('id_task');\n\n  // Only run when all three dropdowns are present (admin time form)\n  if (!invoiceSelect || !projectSelect || !taskSelect) return;\n\n  const apiUrls = window.TIME_API_URLS;\n  if (!apiUrls) return;\n\n  let activeController = null;\n\n  function abortPending() {\n    if (activeController) {\n      activeController.abort();\n    }\n    activeController = new AbortController();\n    return activeController.signal;\n  }\n\n  async function fetchJson(url, signal) {\n    const resp = await fetch(url, { signal });\n    if (!resp.ok) return null;\n    return resp.json();\n  }\n\n  invoiceSelect.addEventListener('change', async function () {\n    const invoiceId = this.value;\n    if (!invoiceId) {\n      // Clear project and task when invoice is deselected\n      projectSelect.value = '';\n      taskSelect.value = '';\n      return;\n    }\n    const signal = abortPending();\n    try {\n      const data = await fetchJson(apiUrls.invoice + invoiceId + '/', signal);\n      if (!data) return;\n      projectSelect.value = data.project_id || '';\n      taskSelect.value = data.default_task_id || '';\n    } catch (e) {\n      if (e.name !== 'AbortError') console.error('Time form invoice API error:', e);\n    }\n  });\n\n  projectSelect.addEventListener('change', async function () {\n    const projectId = this.value;\n    if (!projectId) {\n      taskSelect.value = '';\n      return;\n    }\n    const signal = abortPending();\n    try {\n      const data = await fetchJson(apiUrls.project + projectId + '/', signal);\n      if (!data) return;\n      taskSelect.value = data.default_task_id || '';\n    } catch (e) {\n      if (e.name !== 'AbortError') console.error('Time form project API error:', e);\n    }\n  });\n\n  taskSelect.addEventListener('change', async function () {\n    const taskId = this.value;\n    if (!taskId) return;\n    const signal = abortPending();\n    try {\n      const data = await fetchJson(apiUrls.task + taskId + '/', signal);\n      if (!data) return;\n      if (data.project_id) {\n        projectSelect.value = data.project_id;\n      }\n    } catch (e) {\n      if (e.name !== 'AbortError') console.error('Time form task API error:', e);\n    }\n  });\n}\n\nif (document.readyState === 'loading') {\n  document.addEventListener('DOMContentLoaded', initTimeFormDropdowns);\n} else {\n  initTimeFormDropdowns();\n}\n","// UserContextProvider.js\nimport React from 'react';\nimport { createContext, useContext, useState } from 'react';\nimport PropTypes from 'prop-types';\n\nconst UserContext = createContext();\n\nexport const UserContextProvider = ({ children }) => {\n  const [isAuthenticated, setIsAuthenticated] = useState(false);\n\n  const login = () => {\n    try {\n      // Add logic to handle login, set isAuthenticated to true\n      setIsAuthenticated(true);\n    } catch (error) {\n      console.error('Login error:', error);\n      // Handle error, e.g., show an error message to the user\n    }\n  };\n\n  const logout = () => {\n    try {\n      // Add logic to handle logout, set isAuthenticated to false\n      setIsAuthenticated(false);\n    } catch (error) {\n      console.error('Logout error:', error);\n      // Handle error, e.g., show an error message to the user\n    }\n  };\n\n  return (\n    <UserContext.Provider value={{ isAuthenticated, login, logout }}>\n      {children}\n    </UserContext.Provider>\n  );\n};\n\nUserContextProvider.propTypes = {\n  children: PropTypes.node.isRequired,\n};\n\nexport const useUserContext = () => {\n  const context = useContext(UserContext);\n\n  if (!context) {\n    throw new Error('useUserContext must be used within a UserContextProvider');\n  }\n\n  return context;\n};\n\n// Add PropTypes for the return value of useUserContext\nuseUserContext.propTypes = {\n  isAuthenticated: PropTypes.bool.isRequired,\n  login: PropTypes.func.isRequired,\n  logout: PropTypes.func.isRequired,\n};\n","import { Component } from 'react';\nimport PropTypes from 'prop-types';\n\nclass ErrorBoundary extends Component {\n  constructor (props) {\n    super(props);\n    this.state = { hasError: false };\n  }\n\n  static getDerivedStateFromError () {\n    return { hasError: true };\n  }\n\n  componentDidCatch (error, info) {\n    const { onError } = this.props;\n    console.error(error);\n    onError && onError(error, info);\n  }\n\n  render () {\n    const { children = null } = this.props;\n    const { hasError } = this.state;\n\n    return hasError ? null : children;\n  }\n}\n\nErrorBoundary.propTypes = {\n  onError: PropTypes.func,\n  children: PropTypes.node,\n};\n\nexport default ErrorBoundary;\n","// UserMenu.js\nimport React from 'react';\nimport PropTypes from 'prop-types';\n\nconst UserMenu = ({ isAuthenticated, isSuperuser }) => {\n  return (\n    <div>\n      {isAuthenticated ? (\n        <li className=\"nav-item dropdown text-nowrap\">\n          <a className=\"nav-link text-light text-uppercase exclude-from-hover\" type=\"button\" aria-expanded=\"false\" href=\"/dashboard\">\n            <i className=\"fa-solid fa-leaf me-1\"></i>\n            <span className=\"d-none d-lg-inline\">Dashboard</span>\n            <span className=\"visually-hidden\">Link text</span>\n          </a>\n          <ul className=\"dropdown-menu\">\n            <li><a className=\"dropdown-item\" href=\"/user/profile\">Profile</a></li>\n            <li><a className=\"dropdown-item\" href=\"/dashboard\">Overview</a></li>\n            <li><a className=\"dropdown-item\" href=\"/dashboard/user\">Users</a></li>\n            <li><a className=\"dropdown-item\" href=\"/dashboard/time/create/\">Add Time</a></li>\n            {isSuperuser ? (\n              <>\n                <li><hr className=\"dropdown-divider\"></hr></li>\n                <li><a className=\"dropdown-item\" href=\"https://aclarknet.signin.aws.amazon.com/console\" rel=\"noreferrer\" target=\"_blank\">AWS Console</a></li>\n                <li><a className=\"dropdown-item\" href=\"/blog\">Puput Blog</a></li>\n                <li><a className=\"dropdown-item\" href=\"/django\" rel=\"noreferrer\" target=\"_blank\">Django Admin</a></li>\n                <li><a className=\"dropdown-item\" href=\"https://analytics.google.com\" rel=\"noreferrer\" target=\"_blank\">Google Analytics</a></li>\n                <li><a className=\"dropdown-item\" href=\"https://admin.google.com/ac/home?hl=en\" rel=\"noreferrer\" target=\"_blank\">Google Workspace</a></li>\n                <li><a className=\"dropdown-item\" href=\"https://aclark.net/lounge/\" rel=\"noreferrer\" target=\"_blank\">Lounge IRC</a></li>\n                <li><a className=\"dropdown-item\" href=\"https://logfire.pydantic.dev/aclark4life/aclarknet\" rel=\"noreferrer\" target=\"_blank\">Pydantic Logfire</a></li>\n                <li><a className=\"dropdown-item\" href=\"/explorer\" rel=\"noreferrer\" target=\"_blank\">SQL Explorer</a></li>\n                <li><a className=\"dropdown-item\" href=\"/wagtail\" rel=\"noreferrer\" target=\"_blank\">Wagtail Admin</a></li>\n              </>\n            ) : null}\n            <li><hr className=\"dropdown-divider\"></hr></li>\n            <li><a className=\"dropdown-item\" href=\"/accounts/logout\">Logout</a></li>\n          </ul>\n        </li>\n      ) : (\n        <li className=\"nav-item\">\n          <a className=\"nav-link text-light text-uppercase exclude-from-hover\" href=\"/accounts/login\">\n            <i className=\"fa-solid fa-leaf me-1\"></i>\n            <span className=\"visually-hidden\">Link text</span>\n          </a>\n        </li>\n      )}\n    </div>\n  );\n};\n\nUserMenu.propTypes = {\n  isAuthenticated: PropTypes.bool.isRequired,\n  isSuperuser: PropTypes.bool.isRequired,\n};\n\nexport default UserMenu;\n","// Via ChatGPT\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport React from 'react';\n\nconst Clock = () => {\n  const [date, setDate] = useState(new Date());\n  const [blink, setBlink] = useState(true);\n  const timerID = useRef();\n\n  const tick = useCallback(() => {\n    setDate(new Date());\n    setBlink(prevBlink => !prevBlink);\n  }, []);\n\n  useEffect(() => {\n    timerID.current = setInterval(() => tick(), 1000);\n\n    // Return a cleanup function to be run on component unmount\n    return () => clearInterval(timerID.current);\n  }, [tick]);\n\n  const formattedDate = date.toLocaleDateString(undefined, {\n    weekday: 'short',\n    year: 'numeric',\n    month: 'short',\n    day: 'numeric',\n  });\n\n  const formattedTime = date.toLocaleTimeString(undefined, {\n    hour: 'numeric',\n    minute: 'numeric',\n  });\n\n  return (\n    <>\n      <div style={{ animation: blink ? 'blink 1s infinite' : 'none' }}><span className='me-2'>{formattedDate}</span> {formattedTime}</div>\n    </>\n  );\n};\n\nexport default Clock;\n","import React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport 'bootstrap';\nimport '@fortawesome/fontawesome-free/js/fontawesome';\nimport '@fortawesome/fontawesome-free/js/solid';\nimport '@fortawesome/fontawesome-free/js/regular';\nimport '@fortawesome/fontawesome-free/js/brands';\nimport getDataComponents from '../dataComponents';\nimport UserContextProvider from '../context';\nimport * as components from '../components';\nimport \"../styles/index.scss\";\nimport \"../styles/theme-blue.scss\";\nimport \"./config\";\n\nconst { ErrorBoundary } = components;\nconst dataComponents = getDataComponents(components);\nconst container = document.getElementById('app');\nconst root = createRoot(container);\nconst App = () => (\n    <ErrorBoundary>\n      <UserContextProvider>\n        {dataComponents}\n      </UserContextProvider>\n    </ErrorBoundary>\n);\nroot.render(<App />);\n","// Via pwellever\nimport React from 'react';\nimport { createPortal } from 'react-dom';\n\nconst parseProps = data => Object.entries(data).reduce((result, [key, value]) => {\n  if (value.toLowerCase() === 'true') {\n    value = true;\n  } else if (value.toLowerCase() === 'false') {\n    value = false;\n  } else if (value.toLowerCase() === 'null') {\n    value = null;\n  } else if (!isNaN(parseFloat(value)) && isFinite(value)) {\n    // Parse numeric value\n    value = parseFloat(value);\n  } else if (\n    (value[0] === '[' && value.slice(-1) === ']') || (value[0] === '{' && value.slice(-1) === '}')\n  ) {\n    // Parse JSON strings\n    value = JSON.parse(value);\n  }\n\n  result[key] = value;\n  return result;\n}, {});\n\n// This method of using portals instead of calling ReactDOM.render on individual components\n// ensures that all components are mounted under a single React tree, and are therefore able\n// to share context.\n\nexport default function getPageComponents (components) {\n  const getPortalComponent = domEl => {\n    // The element's \"data-component\" attribute is used to determine which component to render.\n    // All other \"data-*\" attributes are passed as props.\n    const { component: componentName, ...rest } = domEl.dataset;\n    const Component = components[componentName];\n    if (!Component) {\n      console.error(`Component \"${componentName}\" not found.`);\n      return null;\n    }\n    const props = parseProps(rest);\n    domEl.innerHTML = '';\n\n    const { ErrorBoundary } = components;\n    return createPortal(\n      <ErrorBoundary>\n        <Component {...props} />\n      </ErrorBoundary>,\n      domEl,\n    );\n  };\n\n  return Array.from(document.querySelectorAll('[data-component]')).map(getPortalComponent);\n}\n","function handleSelectAll() {\n  var selectAll = document.getElementById(\"select-all\");\n  var checkboxes = document.getElementsByName(\"entry_id\");\n  checkboxes.forEach(function (checkbox) {\n    checkbox.checked = selectAll.checked;\n  });\n}\n\nfunction handleBtnVisibility() {\n  const table = document.getElementById(\"table-select\");\n  const deleteBtn = document.getElementById(\"delete-selected-btn\");\n  const markPaidBtn = document.getElementById(\"mark-paid-selected-btn\");\n  const archiveBtn = document.getElementById(\"archive-selected-btn\");\n  const unarchiveBtn = document.getElementById(\"unarchive-selected-btn\");\n  const htmlBtn = document.getElementById(\"html-selected-btn\");\n  const unhtmlBtn = document.getElementById(\"unhtml-selected-btn\");\n  const saveBtn = document.getElementById(\"save-selected-btn\");\n\n  if (table) {\n    table.addEventListener(\"change\", () => {\n      const checkboxes = table.querySelectorAll('tbody input[type=\"checkbox\"]');\n      const anyChecked = Array.from(checkboxes).some(\n        (checkbox) => checkbox.checked\n      );\n\n      const buttons = [\n        deleteBtn,\n        markPaidBtn,\n        archiveBtn,\n        unarchiveBtn,\n        htmlBtn,\n        unhtmlBtn,\n        saveBtn,\n      ];\n      buttons.forEach((btn) => {\n        if (btn) {\n          btn.style.display = anyChecked ? \"block\" : \"none\";\n        }\n      });\n    });\n  }\n}\n\nvar selectAll = document.getElementById(\"select-all\");\nif (selectAll) {\n  selectAll.addEventListener(\"click\", handleSelectAll);\n}\nhandleBtnVisibility();\n","import Chart from \"chart.js/auto\";\n\n// Declare an array to store chart instances\nvar charts = [];\n\n// Function to render charts\nfunction renderCharts() {\n  // Loop through all chart instances and destroy them\n  for (var i = 0; i < charts.length; i++) {\n    charts[i].destroy();\n  }\n  charts = [];\n\n  // Get all elements with class 'ex-graph'\n  var chartElements = document.getElementsByClassName(\"ex-graph\");\n\n  // Loop through all chart elements\n  for (var i = 0; i < chartElements.length; i++) { // eslint-disable-line no-redeclare\n    var chartElement = chartElements[i];\n\n    // Get chart type and data from data-* attributes\n    var chartType = chartElement.getAttribute(\"data-chart\");\n    var chartData = JSON.parse(chartElement.getAttribute(\"data-dataset\"));\n    var chartOptions = JSON.parse(\n      chartElement.getAttribute(\"data-dataset-options\")\n    );\n    var chartLabels = JSON.parse(chartElement.getAttribute(\"data-labels\"));\n\n    // Create chart using Chart.js\n    var ctx = chartElement.getContext(\"2d\");\n    const chart = new Chart(ctx, {\n      type: chartType,\n      data: {\n        labels: chartLabels,\n        datasets: [\n          {\n            data: chartData,\n            backgroundColor: chartOptions.backgroundColor,\n            borderColor: chartOptions.borderColor,\n          },\n        ],\n      },\n    });\n\n    // Add the chart instance to the charts array\n    charts.push(chart);\n  }\n}\n\n// Call the renderCharts function to initialize and render the charts\nrenderCharts();\n\n// Function to resize charts on window resize\nwindow.addEventListener(\"resize\", function () {\n  // Call the renderCharts function to resize the charts\n  renderCharts();\n});\n"],"names":["myModal","document","getElementById","addEventListener","event","button","relatedTarget","userId","getAttribute","userName","querySelector","value","innerHTML","table","tbody","getElementsByTagName","rows","Array","from","sortTable","columnIndex","ascending","isNumeric","isNaN","textContent","sort","row1","row2","cell1","cell2","value1","parseInt","toLowerCase","value2","forEach","row","appendChild","addHeaderListeners","headers","header","index","classList","contains","isAscending","setAttribute","createSparkline","containerId","canvas","dataset","JSON","parse","labels","width","style","height","color","ctx","getContext","scaleX","length","scaleY","Math","max","min","beginPath","moveTo","i","lineTo","strokeStyle","lineWidth","stroke","console","log","imageLinks","querySelectorAll","modalImage","link","imageUrl","this","src","initTimeFormDropdowns","invoiceSelect","projectSelect","taskSelect","apiUrls","window","TIME_API_URLS","activeController","abortPending","abort","AbortController","signal","async","fetchJson","url","resp","fetch","ok","json","invoiceId","data","invoice","project_id","default_task_id","e","name","error","projectId","project","taskId","task","readyState","UserContext","createContext","UserContextProvider","children","isAuthenticated","setIsAuthenticated","useState","React","Provider","login","logout","propTypes","PropTypes","isRequired","ErrorBoundary","Component","constructor","props","super","state","hasError","getDerivedStateFromError","componentDidCatch","info","onError","render","UserMenu","isSuperuser","className","type","href","rel","target","Clock","date","setDate","Date","blink","setBlink","timerID","useRef","tick","useCallback","prevBlink","useEffect","current","setInterval","clearInterval","formattedDate","toLocaleDateString","undefined","weekday","year","month","day","formattedTime","toLocaleTimeString","hour","minute","animation","components","dataComponents","map","domEl","component","componentName","rest","Object","entries","reduce","result","key","parseFloat","isFinite","slice","createPortal","container","App","createRoot","selectAll","getElementsByName","checkbox","checked","deleteBtn","markPaidBtn","archiveBtn","unarchiveBtn","htmlBtn","unhtmlBtn","saveBtn","checkboxes","anyChecked","some","btn","display","handleBtnVisibility","charts","renderCharts","destroy","chartElements","getElementsByClassName","chartElement","chartType","chartData","chartOptions","chartLabels","chart","Chart","datasets","backgroundColor","borderColor","push"],"ignoreList":[],"sourceRoot":""}