{
  "version": 3,
  "sources": ["sync_log.js"],
  "sourcesContent": ["/*\n * static/js/sync_log.js \u2014 Manage-page sync-log panel (SNOW-482).\n *\n * Paints the ``#sync-log-list`` <ul>\n * (``accounts/templates/accounts/partials/_sync_log_body.html``) with the\n * newest rows from ``window.pwaDb.getSyncLog()`` on load. Only included\n * on the page when the ``sync_log`` waffle flag is active\n * (``accounts/templates/accounts/manage.html``), but self-guards on\n * ``window.pwaDb`` presence regardless \u2014 IndexedDB can be unavailable\n * (private mode, the SNOW-375 Reset Required state).\n *\n * Rows are plain ``{id, at, path}`` objects written by\n * ``static/js/pwa_offline.js``'s ``appendSyncLogEntry`` for every\n * qualifying same-origin, un-cached response \u2014 telemetry flushes\n * excluded at both ends, see ``EXCLUDED_PATHS``. \"Reset local data on this\n * device\" (SNOW-378, ``pwa_reset.js``) wipes the whole IndexedDB\n * database, so the log clears along with everything else \u2014 no separate\n * clear affordance needed here.\n */\n\n(function () {\n  'use strict';\n\n  const LIST_ID = 'sync-log-list';\n\n  // Paths pwa_offline.js's SYNC_LOG_EXCLUDED_PATHS now refuses to write.\n  // Filtering on read as well is what clears the panel on a device that\n  // already banked a hundred telemetry flushes \u2014 those rows age out of\n  // the capped store on their own, and until they do they must not be\n  // painted.\n  const EXCLUDED_PATHS = new Set(['/api/telemetry', '/api/telemetry/']);\n\n  // SNOW-620: server-translated placeholder copy, read back from the\n  // template accounts/partials/_sync_log_body.html renders. The literals\n  // are the English fallback \u2014 see static/js/i18n_strings.js.\n  const STRINGS = self.pwaStrings.read('sync-log-strings-template', {\n    unavailable: 'Sync log unavailable on this device.',\n    empty: 'No syncs yet.',\n    failed: 'Could not load the sync log.',\n  });\n\n  /**\n   * Format an ISO timestamp as \"HH:MM DD/MM\" without pulling Intl.\n   * Falls back to the raw string on parse failure.\n   *\n   * @param {string} value\n   * @returns {string}\n   */\n  function formatShort(value) {\n    const d = new Date(value);\n    if (Number.isNaN(d.valueOf())) return value;\n    const pad = (n) => String(n).padStart(2, '0');\n    return `${pad(d.getHours())}:${pad(d.getMinutes())} ${pad(d.getDate())}/${pad(d.getMonth() + 1)}`;\n  }\n\n  /**\n   * Replace the list's contents with a single muted placeholder row.\n   *\n   * @param {HTMLElement} list\n   * @param {string} text\n   */\n  function renderPlaceholder(list, text) {\n    list.textContent = '';\n    const li = document.createElement('li');\n    li.className = 'px-4 py-3 text-text-3';\n    li.setAttribute('data-role', 'sync-log-placeholder');\n    li.textContent = text;\n    list.appendChild(li);\n  }\n\n  /**\n   * Build one row for a ``log:sync`` entry.\n   *\n   * @param {{at: string, path: string}} entry\n   * @returns {HTMLLIElement}\n   */\n  function buildRow(entry) {\n    const li = document.createElement('li');\n    li.className = 'flex items-center justify-between gap-3 px-4 py-3';\n    li.setAttribute('data-testid', 'sync-log-row');\n\n    const path = document.createElement('span');\n    path.className = 'text-text-1 truncate';\n    path.textContent = entry.path || '';\n\n    const at = document.createElement('span');\n    at.className = 'text-text-3 shrink-0 font-mono text-caption';\n    at.textContent = formatShort(entry.at);\n\n    li.appendChild(path);\n    li.appendChild(at);\n    return li;\n  }\n\n  /**\n   * Read the sync log and paint it into ``#sync-log-list``, replacing\n   * the \"Loading\u2026\" placeholder from the template shell. Never throws \u2014\n   * an IndexedDB failure degrades to a muted placeholder row rather than\n   * breaking the rest of the page.\n   */\n  async function render() {\n    const list = document.getElementById(LIST_ID);\n    if (!list) return;\n\n    if (!window.pwaDb || typeof window.pwaDb.getSyncLog !== 'function') {\n      renderPlaceholder(list, STRINGS.unavailable);\n      return;\n    }\n\n    try {\n      const rows = await window.pwaDb.getSyncLog();\n      const visible = (rows || []).filter((entry) => !EXCLUDED_PATHS.has(entry.path));\n      if (visible.length === 0) {\n        renderPlaceholder(list, STRINGS.empty);\n        return;\n      }\n      list.textContent = '';\n      visible.forEach((entry) => list.appendChild(buildRow(entry)));\n    } catch (_err) {\n      renderPlaceholder(list, STRINGS.failed);\n    }\n  }\n\n  // Deferred scripts execute in DOCUMENT ORDER, and this one's <script>\n  // tag (inside the manage.html content block) appears BEFORE db.js's\n  // (declared in base.html, after the content block) \u2014 so calling\n  // render() eagerly here would race window.pwaDb into existence.\n  // DOMContentLoaded fires only once every deferred script, db.js\n  // included, has already run, which is what actually guarantees\n  // window.pwaDb is defined by the time render() executes.\n  document.addEventListener('DOMContentLoaded', render);\n})();\n"],
  "mappings": "CAoBC,UAAY,CACX,aAEA,MAAMA,EAAU,gBAOVC,EAAiB,IAAI,IAAI,CAAC,iBAAkB,iBAAiB,CAAC,EAK9DC,EAAU,KAAK,WAAW,KAAK,4BAA6B,CAChE,YAAa,uCACb,MAAO,gBACP,OAAQ,8BACV,CAAC,EASD,SAASC,EAAYC,EAAO,CAC1B,MAAMC,EAAI,IAAI,KAAKD,CAAK,EACxB,GAAI,OAAO,MAAMC,EAAE,QAAQ,CAAC,EAAG,OAAOD,EACtC,MAAME,EAAOC,GAAM,OAAOA,CAAC,EAAE,SAAS,EAAG,GAAG,EAC5C,MAAO,GAAGD,EAAID,EAAE,SAAS,CAAC,CAAC,IAAIC,EAAID,EAAE,WAAW,CAAC,CAAC,IAAIC,EAAID,EAAE,QAAQ,CAAC,CAAC,IAAIC,EAAID,EAAE,SAAS,EAAI,CAAC,CAAC,EACjG,CAQA,SAASG,EAAkBC,EAAMC,EAAM,CACrCD,EAAK,YAAc,GACnB,MAAME,EAAK,SAAS,cAAc,IAAI,EACtCA,EAAG,UAAY,wBACfA,EAAG,aAAa,YAAa,sBAAsB,EACnDA,EAAG,YAAcD,EACjBD,EAAK,YAAYE,CAAE,CACrB,CAQA,SAASC,EAASC,EAAO,CACvB,MAAMF,EAAK,SAAS,cAAc,IAAI,EACtCA,EAAG,UAAY,oDACfA,EAAG,aAAa,cAAe,cAAc,EAE7C,MAAMG,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,UAAY,uBACjBA,EAAK,YAAcD,EAAM,MAAQ,GAEjC,MAAME,EAAK,SAAS,cAAc,MAAM,EACxC,OAAAA,EAAG,UAAY,8CACfA,EAAG,YAAcZ,EAAYU,EAAM,EAAE,EAErCF,EAAG,YAAYG,CAAI,EACnBH,EAAG,YAAYI,CAAE,EACVJ,CACT,CAQA,eAAeK,GAAS,CACtB,MAAMP,EAAO,SAAS,eAAeT,CAAO,EAC5C,GAAKS,EAEL,IAAI,CAAC,OAAO,OAAS,OAAO,OAAO,MAAM,YAAe,WAAY,CAClED,EAAkBC,EAAMP,EAAQ,WAAW,EAC3C,MACF,CAEA,GAAI,CAEF,MAAMe,GADO,MAAM,OAAO,MAAM,WAAW,GAClB,CAAC,GAAG,OAAQJ,GAAU,CAACZ,EAAe,IAAIY,EAAM,IAAI,CAAC,EAC9E,GAAII,EAAQ,SAAW,EAAG,CACxBT,EAAkBC,EAAMP,EAAQ,KAAK,EACrC,MACF,CACAO,EAAK,YAAc,GACnBQ,EAAQ,QAASJ,GAAUJ,EAAK,YAAYG,EAASC,CAAK,CAAC,CAAC,CAC9D,MAAe,CACbL,EAAkBC,EAAMP,EAAQ,MAAM,CACxC,EACF,CASA,SAAS,iBAAiB,mBAAoBc,CAAM,CACtD,GAAG",
  "names": ["LIST_ID", "EXCLUDED_PATHS", "STRINGS", "formatShort", "value", "d", "pad", "n", "renderPlaceholder", "list", "text", "li", "buildRow", "entry", "path", "at", "render", "visible"]
}
