@campfire-interactive/volume-intelligence-ui 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +36 -1
- package/dist/index.js +809 -359
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// src/styles.css
|
|
28
|
-
styleInject(".cfi-volume-import {\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n font-size: var(--cfi-font-size-base, 14px);\n color: var(--cfi-color-gray-900, #111827);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 12px);\n max-width: 640px;\n}\n.cfi-volume-import .cfi-vi-field {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-xs, 4px);\n}\n.cfi-volume-import .cfi-vi-row {\n display: flex;\n gap: var(--cfi-spacing-md, 12px);\n flex-wrap: wrap;\n}\n.cfi-volume-import .cfi-vi-row .cfi-vi-field {\n flex: 1 1 8rem;\n}\n.cfi-volume-import .cfi-vi-label {\n font-size: var(--cfi-font-size-sm, 12px);\n font-weight: 600;\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-volume-import .cfi-vi-select,\n.cfi-volume-import .cfi-vi-file {\n padding: 6px 8px;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-md, 6px);\n background: #fff;\n font: inherit;\n color: inherit;\n}\n.cfi-volume-import .cfi-vi-select:focus,\n.cfi-volume-import .cfi-vi-file:focus {\n outline: 2px solid var(--cfi-color-primary-600, #2563eb);\n outline-offset: 1px;\n}\n.cfi-volume-import .cfi-vi-button {\n display: inline-flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 6px);\n align-self: flex-start;\n padding: 8px 14px;\n border: none;\n border-radius: var(--cfi-radius-md, 6px);\n background: var(--cfi-color-primary-600, #2563eb);\n color: #fff;\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.cfi-volume-import .cfi-vi-button:hover:not(:disabled) {\n background: var(--cfi-color-primary-700, #1d4ed8);\n}\n.cfi-volume-import .cfi-vi-button:disabled {\n background: var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-500, #6b7280);\n cursor: not-allowed;\n}\n.cfi-volume-import .cfi-vi-loading,\n.cfi-volume-import .cfi-vi-alert {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 6px);\n padding: 8px 10px;\n border-radius: var(--cfi-radius-md, 6px);\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-volume-import .cfi-vi-alert--error {\n background: var(--cfi-color-gray-100, #fef2f2);\n color: var(--cfi-color-error, #b91c1c);\n}\n.cfi-volume-import .cfi-vi-alert--warn {\n background: #fffbeb;\n color: #92400e;\n align-items: flex-start;\n}\n.cfi-volume-import .cfi-vi-blockers {\n margin: 0;\n padding-left: 1.1rem;\n}\n.cfi-volume-import .cfi-vi-status {\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-md, 6px);\n padding: var(--cfi-spacing-md, 12px);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 8px);\n}\n.cfi-volume-import .cfi-vi-status-head {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 8px);\n}\n.cfi-volume-import .cfi-vi-filename {\n font-weight: 600;\n}\n.cfi-volume-import .cfi-vi-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n border-radius: 999px;\n font-size: var(--cfi-font-size-xs, 11px);\n text-transform: capitalize;\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-volume-import .cfi-vi-badge--done {\n background: #dcfce7;\n color: #166534;\n}\n.cfi-volume-import .cfi-vi-badge--done_with_errors {\n background: #fef9c3;\n color: #854d0e;\n}\n.cfi-volume-import .cfi-vi-badge--failed {\n background: #fee2e2;\n color: #991b1b;\n}\n.cfi-volume-import .cfi-vi-badge--processing,\n.cfi-volume-import .cfi-vi-badge--pending,\n.cfi-volume-import .cfi-vi-badge--awaiting_calendar {\n background: #dbeafe;\n color: #1e40af;\n}\n.cfi-volume-import .cfi-vi-link {\n background: none;\n border: none;\n padding: 0;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: var(--cfi-color-primary-600, #2563eb);\n font: inherit;\n cursor: pointer;\n}\n.cfi-volume-import .cfi-vi-stats {\n display: flex;\n gap: var(--cfi-spacing-md, 12px);\n color: var(--cfi-color-gray-600, #4b5563);\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-volume-import .cfi-vi-errors {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-volume-import .cfi-vi-errors th,\n.cfi-volume-import .cfi-vi-errors td {\n text-align: left;\n padding: 4px 8px;\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n vertical-align: top;\n}\n.cfi-volume-import .cfi-vi-spin {\n animation: cfi-vi-spin 0.8s linear infinite;\n}\n@keyframes cfi-vi-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.cfi-vi {\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n font-size: var(--cfi-font-size-base, 14px);\n color: var(--cfi-color-gray-900, #111827);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 12px);\n}\n.cfi-vi *,\n.cfi-vi *::before,\n.cfi-vi *::after {\n box-sizing: border-box;\n}\n.cfi-vi .cfi-vi-row {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 8px);\n}\n.cfi-vi .cfi-vi-row--between {\n justify-content: space-between;\n}\n.cfi-vi .cfi-vi-spacer {\n flex: 1;\n}\n.cfi-vi .cfi-vi-muted {\n color: var(--cfi-color-gray-600, #4b5563);\n}\n.cfi-vi .cfi-vi-error {\n color: var(--cfi-color-error, #b91c1c);\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-vi .cfi-vi-mono {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n monospace;\n font-size: var(--cfi-font-size-xs, 11px);\n}\n.cfi-vi .cfi-vi-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border-radius: var(--cfi-radius-md, 6px);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n border: 1px solid transparent;\n white-space: nowrap;\n}\n.cfi-vi .cfi-vi-btn--sm {\n padding: 4px 10px;\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-vi .cfi-vi-btn--md {\n padding: 8px 14px;\n}\n.cfi-vi .cfi-vi-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.cfi-vi .cfi-vi-btn--primary {\n background: var(--cfi-color-primary-600, #2563eb);\n color: #fff;\n}\n.cfi-vi .cfi-vi-btn--primary:hover:not(:disabled) {\n background: var(--cfi-color-primary-700, #1d4ed8);\n}\n.cfi-vi .cfi-vi-btn--outline {\n background: #fff;\n border-color: var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-vi .cfi-vi-btn--outline:hover:not(:disabled) {\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-vi .cfi-vi-btn--ghost {\n background: transparent;\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi .cfi-vi-btn--ghost:hover:not(:disabled) {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-vi .cfi-vi-btn--destructive {\n background: var(--cfi-color-error, #dc2626);\n color: #fff;\n}\n.cfi-vi .cfi-vi-btn--destructive:hover:not(:disabled) {\n filter: brightness(0.92);\n}\n.cfi-vi .cfi-vi-icon-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n color: var(--cfi-color-gray-500, #6b7280);\n border-radius: var(--cfi-radius-sm, 4px);\n display: inline-flex;\n}\n.cfi-vi .cfi-vi-icon-btn:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-vi .cfi-vi-tag {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 1px 8px;\n border-radius: 999px;\n font-size: var(--cfi-font-size-xs, 11px);\n font-weight: 600;\n}\n.cfi-vi .cfi-vi-tag--default {\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi .cfi-vi-tag--outline {\n background: transparent;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi .cfi-vi-tag--secondary {\n background: var(--cfi-color-gray-200, #e5e7eb);\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi .cfi-vi-tag--success {\n background: #16a34a;\n color: #fff;\n}\n.cfi-vi .cfi-vi-tag--purple {\n background: var(--cfi-color-violet-600, #7c3aed);\n color: #fff;\n}\n.cfi-vi .cfi-vi-card {\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-lg, 8px);\n background: #fff;\n}\n.cfi-vi .cfi-vi-card--active {\n border-color: #86efac;\n background: #f0fdf4;\n}\n.cfi-vi .cfi-vi-card--hover:hover {\n border-color: var(--cfi-color-primary-600, #2563eb);\n}\n.cfi-vi .cfi-vi-card-head {\n padding: var(--cfi-spacing-md, 12px);\n padding-bottom: var(--cfi-spacing-sm, 8px);\n}\n.cfi-vi .cfi-vi-card-body {\n padding: 0 var(--cfi-spacing-md, 12px) var(--cfi-spacing-md, 12px);\n}\n.cfi-vi .cfi-vi-card-title {\n font-size: var(--cfi-font-size-base, 15px);\n font-weight: 600;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.cfi-vi .cfi-vi-link {\n background: none;\n border: none;\n padding: 0;\n color: inherit;\n font: inherit;\n cursor: pointer;\n text-align: left;\n}\n.cfi-vi .cfi-vi-link:hover {\n text-decoration: underline;\n}\n.cfi-vi .cfi-vi-field {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-xs, 4px);\n}\n.cfi-vi .cfi-vi-label {\n font-size: var(--cfi-font-size-sm, 12px);\n font-weight: 600;\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi .cfi-vi-hint {\n font-size: var(--cfi-font-size-xs, 11px);\n color: var(--cfi-color-gray-500, #6b7280);\n margin: 2px 0 0;\n}\n.cfi-vi .cfi-vi-input,\n.cfi-vi select.cfi-vi-input {\n padding: 6px 8px;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-md, 6px);\n background: #fff;\n font: inherit;\n color: inherit;\n width: 100%;\n}\n.cfi-vi .cfi-vi-input:focus {\n outline: 2px solid var(--cfi-color-primary-600, #2563eb);\n outline-offset: 1px;\n}\n.cfi-vi-modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 50;\n padding: 16px;\n}\n.cfi-vi-modal {\n background: #fff;\n border-radius: var(--cfi-radius-lg, 8px);\n width: 100%;\n max-width: 32rem;\n max-height: 90vh;\n overflow: auto;\n box-shadow: var(--cfi-shadow-lg, 0 10px 30px rgba(0,0,0,0.2));\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n color: var(--cfi-color-gray-900, #111827);\n display: flex;\n flex-direction: column;\n}\n.cfi-vi-modal-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--cfi-spacing-md, 14px);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-vi-modal-title {\n font-size: var(--cfi-font-size-lg, 16px);\n font-weight: 600;\n margin: 0;\n}\n.cfi-vi-modal-body {\n padding: var(--cfi-spacing-md, 14px);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 12px);\n}\n.cfi-vi-modal-foot {\n display: flex;\n justify-content: flex-end;\n gap: var(--cfi-spacing-sm, 8px);\n padding: var(--cfi-spacing-md, 14px);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-vi-icon-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n color: var(--cfi-color-gray-500, #6b7280);\n border-radius: 4px;\n display: inline-flex;\n}\n.cfi-vi .cfi-vi-spinner {\n display: inline-block;\n border: 2px solid var(--cfi-color-gray-300, #d1d5db);\n border-top-color: var(--cfi-color-primary-600, #2563eb);\n border-radius: 50%;\n animation: cfi-vi-spin 0.8s linear infinite;\n}\n.cfi-vi .cfi-vi-list {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 10px);\n}\n.cfi-vi .cfi-vi-list-head {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n}\n.cfi-vi .cfi-vi-h1 {\n font-size: var(--cfi-font-size-lg, 18px);\n font-weight: 600;\n margin: 0;\n}\n.cfi-vi .cfi-vi-active-line {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: var(--cfi-font-size-sm, 13px);\n color: var(--cfi-color-gray-600, #4b5563);\n margin-top: 2px;\n}\n.cfi-vi .cfi-vi-active-name {\n font-weight: 600;\n color: #15803d;\n}\n.cfi-vi .cfi-vi-active-extras {\n margin-top: var(--cfi-spacing-md, 16px);\n padding-top: var(--cfi-spacing-md, 16px);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 16px);\n}\n.cfi-vi-mapper {\n display: grid;\n grid-template-columns: 1fr;\n gap: var(--cfi-spacing-lg, 24px);\n align-items: start;\n}\n@media (min-width: 1024px) {\n .cfi-vi-mapper {\n grid-template-columns: 1fr 1fr;\n }\n}\n.cfi-vi-mapper .cfi-vi-mapper-col {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-lg, 24px);\n min-width: 0;\n}\n.cfi-vi-mapper .cfi-vi-mapper-section {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 8px);\n}\n.cfi-vi-mapper .cfi-vi-mapper-section-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n.cfi-vi-mapper .cfi-vi-mapper-h3 {\n font-size: var(--cfi-font-size-xs, 11px);\n font-weight: 700;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--cfi-color-gray-500, #6b7280);\n margin: 0;\n}\n.cfi-vi-mapper .cfi-vi-mapper-note {\n font-size: var(--cfi-font-size-xs, 11px);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-vi-mapper .cfi-vi-mapper-box {\n border: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n border-radius: var(--cfi-radius-lg, 8px);\n background: #fff;\n padding: var(--cfi-spacing-md, 14px);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.cfi-vi-mapper .cfi-vi-mapper-err {\n font-size: var(--cfi-font-size-xs, 11px);\n color: var(--cfi-color-error, #b91c1c);\n margin: 2px 0 0;\n}\n.cfi-vi-mapper .cfi-vi-mapper-save {\n display: flex;\n align-items: center;\n gap: 12px;\n padding-top: 4px;\n}\n.cfi-vi-mapper .cfi-vi-mapper-dirty {\n font-size: var(--cfi-font-size-xs, 11px);\n color: #b45309;\n}\n.cfi-vi-mapper .cfi-vi-hier-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.cfi-vi-mapper .cfi-vi-hier-elbow {\n width: 18px;\n align-self: stretch;\n border-left: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n height: 18px;\n margin-bottom: 9px;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-hier-dot {\n width: 14px;\n height: 14px;\n border-radius: 50%;\n border: 2px solid var(--cfi-color-gray-300, #d1d5db);\n background: #fff;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-hier-dot--filled {\n border-color: var(--cfi-color-primary-600, #6366f1);\n background: var(--cfi-color-primary-50, #eef2ff);\n}\n.cfi-vi-mapper .cfi-vi-hier-name {\n font-size: var(--cfi-font-size-xs, 12px);\n font-weight: 600;\n color: var(--cfi-color-gray-600, #4b5563);\n width: 96px;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-leaf {\n font-size: 10px;\n font-weight: 600;\n color: #b45309;\n background: #fffbeb;\n border: 1px solid #fde68a;\n padding: 1px 6px;\n border-radius: 999px;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-dropzone {\n flex: 1;\n min-height: 36px;\n border-radius: var(--cfi-radius-md, 6px);\n border: 2px solid;\n display: flex;\n align-items: center;\n padding: 0 10px;\n min-width: 0;\n transition: all 0.12s;\n}\n.cfi-vi-mapper .cfi-vi-dropzone--active {\n border-color: var(--cfi-color-primary-600, #6366f1);\n background: var(--cfi-color-primary-50, #eef2ff);\n}\n.cfi-vi-mapper .cfi-vi-dropzone--filled {\n border-style: solid;\n border-color: var(--cfi-color-gray-200, #e5e7eb);\n background: #fff;\n}\n.cfi-vi-mapper .cfi-vi-dropzone--empty {\n border-style: dashed;\n border-color: var(--cfi-color-gray-200, #e5e7eb);\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-vi-mapper .cfi-vi-dropzone--covered {\n border-style: solid;\n border-color: #a7f3d0;\n background: #ecfdf5;\n}\n.cfi-vi-mapper .cfi-vi-dropzone-ph {\n font-size: var(--cfi-font-size-xs, 12px);\n color: var(--cfi-color-gray-400, #9ca3af);\n user-select: none;\n}\n.cfi-vi-mapper .cfi-vi-base-hint {\n font-size: 10px;\n font-family: ui-monospace, monospace;\n color: #1d4ed8;\n background: #eff6ff;\n border: 1px solid #bfdbfe;\n padding: 1px 6px;\n border-radius: 4px;\n flex-shrink: 0;\n white-space: nowrap;\n}\n.cfi-vi-mapper .cfi-vi-auto-row {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n.cfi-vi-mapper .cfi-vi-auto-label {\n width: 160px;\n flex-shrink: 0;\n padding-top: 6px;\n}\n.cfi-vi-mapper .cfi-vi-auto-label-text {\n font-size: var(--cfi-font-size-xs, 12px);\n font-weight: 600;\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi-mapper .cfi-vi-auto-cover {\n font-size: 10px;\n margin: 2px 0 0;\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-vi-mapper .cfi-vi-auto-cover--on {\n color: #047857;\n}\n.cfi-vi-mapper .cfi-vi-auto-auto {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n min-width: 0;\n color: #047857;\n}\n.cfi-vi-mapper .cfi-vi-auto-auto-label {\n font-size: var(--cfi-font-size-xs, 12px);\n font-family: ui-monospace, monospace;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.cfi-vi-mapper .cfi-vi-auto-auto-tag {\n font-size: 10px;\n font-style: italic;\n color: #059669;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-auto-transform {\n width: 224px;\n flex-shrink: 0;\n padding-top: 6px;\n font-size: 11px;\n color: var(--cfi-color-gray-500, #6b7280);\n line-height: 1.3;\n}\n.cfi-vi-mapper .cfi-vi-auto-transform-label {\n font-weight: 600;\n}\n.cfi-vi-mapper .cfi-vi-pool-col {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 8px);\n}\n@media (min-width: 1024px) {\n .cfi-vi-mapper .cfi-vi-pool-col {\n position: sticky;\n top: 16px;\n align-self: start;\n }\n}\n.cfi-vi-mapper .cfi-vi-search {\n position: relative;\n}\n.cfi-vi-mapper .cfi-vi-search .cfi-vi-input {\n padding-left: 28px;\n}\n.cfi-vi-mapper .cfi-vi-search-icon {\n position: absolute;\n left: 8px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--cfi-color-gray-400, #9ca3af);\n pointer-events: none;\n}\n.cfi-vi-mapper .cfi-vi-pool {\n border: 2px dashed var(--cfi-color-gray-200, #e5e7eb);\n background: var(--cfi-color-gray-50, #f9fafb);\n border-radius: var(--cfi-radius-lg, 8px);\n padding: 12px;\n min-height: 200px;\n max-height: 600px;\n overflow-y: auto;\n}\n.cfi-vi-mapper .cfi-vi-pool--active {\n border-color: var(--cfi-color-primary-600, #818cf8);\n background: var(--cfi-color-primary-50, #eef2ff);\n}\n.cfi-vi-mapper .cfi-vi-pool-empty {\n font-size: var(--cfi-font-size-xs, 12px);\n color: var(--cfi-color-gray-400, #9ca3af);\n font-style: italic;\n}\n.cfi-vi-mapper .cfi-vi-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n.cfi-vi-mapper .cfi-vi-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: var(--cfi-radius-md, 6px);\n background: #fff;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n cursor: grab;\n user-select: none;\n font-size: var(--cfi-font-size-xs, 12px);\n font-family: ui-monospace, monospace;\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi-mapper .cfi-vi-chip:hover {\n border-color: var(--cfi-color-primary-600, #818cf8);\n background: var(--cfi-color-primary-50, #eef2ff);\n}\n.cfi-vi-mapper .cfi-vi-chip:active {\n cursor: grabbing;\n}\n.cfi-vi-mapper .cfi-vi-chip--assigned {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n min-width: 0;\n cursor: grab;\n}\n.cfi-vi-mapper .cfi-vi-chip--assigned:active {\n cursor: grabbing;\n}\n.cfi-vi-mapper .cfi-vi-chip-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--cfi-color-gray-400, #9ca3af);\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-chip-dot--on {\n background: var(--cfi-color-primary-600, #6366f1);\n}\n.cfi-vi-mapper .cfi-vi-chip-label {\n font-size: var(--cfi-font-size-xs, 12px);\n font-family: ui-monospace, monospace;\n color: #3730a3;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.cfi-vi-mapper .cfi-vi-chip-x {\n margin-left: 4px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n color: var(--cfi-color-gray-400, #9ca3af);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-chip-x:hover {\n background: #fee2e2;\n color: #ef4444;\n}\n.cfi-vi .cfi-vi-spin {\n animation: cfi-vi-spin 0.8s linear infinite;\n}\n.cfi-vi .cfi-vi-detail {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-lg, 20px);\n}\n.cfi-vi .cfi-vi-h2 {\n font-size: var(--cfi-font-size-base, 15px);\n font-weight: 600;\n margin: 0;\n}\n.cfi-vi .cfi-vi-panel {\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-md, 6px);\n background: #fff;\n padding: var(--cfi-spacing-md, 16px);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 12px);\n}\n.cfi-vi .cfi-vi-grid2 {\n display: grid;\n grid-template-columns: 1fr;\n gap: var(--cfi-spacing-md, 16px);\n}\n@media (min-width: 768px) {\n .cfi-vi .cfi-vi-grid2 {\n grid-template-columns: 1fr 1fr;\n }\n}\n.cfi-vi .cfi-vi-lock {\n display: flex;\n align-items: center;\n gap: 8px;\n border: 1px solid #fde68a;\n background: #fffbeb;\n color: #92400e;\n border-radius: var(--cfi-radius-md, 6px);\n padding: 8px 12px;\n font-size: var(--cfi-font-size-xs, 12px);\n}\n.cfi-vi .cfi-vi-table {\n width: 100%;\n border-collapse: collapse;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-md, 6px);\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-vi .cfi-vi-table th,\n.cfi-vi .cfi-vi-table td {\n text-align: left;\n padding: 6px 10px;\n border-bottom: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n vertical-align: middle;\n}\n.cfi-vi .cfi-vi-table th {\n font-size: var(--cfi-font-size-xs, 11px);\n font-weight: 600;\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-vi .cfi-vi-table tr:last-child td {\n border-bottom: none;\n}\n.cfi-vi .cfi-vi-danger {\n border: 1px solid rgba(220, 38, 38, 0.4);\n background: rgba(220, 38, 38, 0.05);\n border-radius: var(--cfi-radius-md, 6px);\n padding: var(--cfi-spacing-md, 16px);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 12px);\n}\n.cfi-vi .cfi-vi-aliases {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 12px);\n}\n.cfi-vi .cfi-vi-alias-rows {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n");
|
|
28
|
+
styleInject(".cfi-volume-import {\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n font-size: var(--cfi-font-size-base, 14px);\n color: var(--cfi-color-gray-900, #111827);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 12px);\n max-width: 640px;\n}\n.cfi-volume-import .cfi-vi-field {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-xs, 4px);\n}\n.cfi-volume-import .cfi-vi-row {\n display: flex;\n gap: var(--cfi-spacing-md, 12px);\n flex-wrap: wrap;\n}\n.cfi-volume-import .cfi-vi-row .cfi-vi-field {\n flex: 1 1 8rem;\n}\n.cfi-volume-import .cfi-vi-label {\n font-size: var(--cfi-font-size-sm, 12px);\n font-weight: 600;\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-volume-import .cfi-vi-select,\n.cfi-volume-import .cfi-vi-file {\n padding: 6px 8px;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-md, 6px);\n background: #fff;\n font: inherit;\n color: inherit;\n}\n.cfi-volume-import .cfi-vi-select:focus,\n.cfi-volume-import .cfi-vi-file:focus {\n outline: 2px solid var(--cfi-color-primary-600, #2563eb);\n outline-offset: 1px;\n}\n.cfi-volume-import .cfi-vi-button {\n display: inline-flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 6px);\n align-self: flex-start;\n padding: 8px 14px;\n border: none;\n border-radius: var(--cfi-radius-md, 6px);\n background: var(--cfi-color-primary-600, #2563eb);\n color: #fff;\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.cfi-volume-import .cfi-vi-button:hover:not(:disabled) {\n background: var(--cfi-color-primary-700, #1d4ed8);\n}\n.cfi-volume-import .cfi-vi-button:disabled {\n background: var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-500, #6b7280);\n cursor: not-allowed;\n}\n.cfi-volume-import .cfi-vi-loading,\n.cfi-volume-import .cfi-vi-alert {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 6px);\n padding: 8px 10px;\n border-radius: var(--cfi-radius-md, 6px);\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-volume-import .cfi-vi-alert--error {\n background: var(--cfi-color-gray-100, #fef2f2);\n color: var(--cfi-color-error, #b91c1c);\n}\n.cfi-volume-import .cfi-vi-alert--warn {\n background: #fffbeb;\n color: #92400e;\n align-items: flex-start;\n}\n.cfi-volume-import .cfi-vi-blockers {\n margin: 0;\n padding-left: 1.1rem;\n}\n.cfi-volume-import .cfi-vi-status {\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-md, 6px);\n padding: var(--cfi-spacing-md, 12px);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 8px);\n}\n.cfi-volume-import .cfi-vi-status-head {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 8px);\n}\n.cfi-volume-import .cfi-vi-filename {\n font-weight: 600;\n}\n.cfi-volume-import .cfi-vi-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n border-radius: 999px;\n font-size: var(--cfi-font-size-xs, 11px);\n text-transform: capitalize;\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-volume-import .cfi-vi-badge--done {\n background: #dcfce7;\n color: #166534;\n}\n.cfi-volume-import .cfi-vi-badge--done_with_errors {\n background: #fef9c3;\n color: #854d0e;\n}\n.cfi-volume-import .cfi-vi-badge--failed {\n background: #fee2e2;\n color: #991b1b;\n}\n.cfi-volume-import .cfi-vi-badge--processing,\n.cfi-volume-import .cfi-vi-badge--pending,\n.cfi-volume-import .cfi-vi-badge--awaiting_calendar {\n background: #dbeafe;\n color: #1e40af;\n}\n.cfi-volume-import .cfi-vi-link {\n background: none;\n border: none;\n padding: 0;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: var(--cfi-color-primary-600, #2563eb);\n font: inherit;\n cursor: pointer;\n}\n.cfi-volume-import .cfi-vi-stats {\n display: flex;\n gap: var(--cfi-spacing-md, 12px);\n color: var(--cfi-color-gray-600, #4b5563);\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-volume-import .cfi-vi-errors {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-volume-import .cfi-vi-errors th,\n.cfi-volume-import .cfi-vi-errors td {\n text-align: left;\n padding: 4px 8px;\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n vertical-align: top;\n}\n.cfi-volume-import .cfi-vi-spin {\n animation: cfi-vi-spin 0.8s linear infinite;\n}\n@keyframes cfi-vi-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.cfi-vi {\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n font-size: var(--cfi-font-size-base, 14px);\n color: var(--cfi-color-gray-900, #111827);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 12px);\n}\n.cfi-vi *,\n.cfi-vi *::before,\n.cfi-vi *::after {\n box-sizing: border-box;\n}\n.cfi-vi .cfi-vi-row {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 8px);\n}\n.cfi-vi .cfi-vi-row--between {\n justify-content: space-between;\n}\n.cfi-vi .cfi-vi-spacer {\n flex: 1;\n}\n.cfi-vi .cfi-vi-muted {\n color: var(--cfi-color-gray-600, #4b5563);\n}\n.cfi-vi .cfi-vi-error {\n color: var(--cfi-color-error, #b91c1c);\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-vi .cfi-vi-mono {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n monospace;\n font-size: var(--cfi-font-size-xs, 11px);\n}\n.cfi-vi .cfi-vi-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border-radius: var(--cfi-radius-md, 6px);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n border: 1px solid transparent;\n white-space: nowrap;\n}\n.cfi-vi .cfi-vi-btn--sm {\n padding: 4px 10px;\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-vi .cfi-vi-btn--md {\n padding: 8px 14px;\n}\n.cfi-vi .cfi-vi-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.cfi-vi .cfi-vi-btn--primary {\n background: var(--cfi-color-primary-600, #2563eb);\n color: #fff;\n}\n.cfi-vi .cfi-vi-btn--primary:hover:not(:disabled) {\n background: var(--cfi-color-primary-700, #1d4ed8);\n}\n.cfi-vi .cfi-vi-btn--outline {\n background: #fff;\n border-color: var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-vi .cfi-vi-btn--outline:hover:not(:disabled) {\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-vi .cfi-vi-btn--ghost {\n background: transparent;\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi .cfi-vi-btn--ghost:hover:not(:disabled) {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-vi .cfi-vi-btn--destructive {\n background: var(--cfi-color-error, #dc2626);\n color: #fff;\n}\n.cfi-vi .cfi-vi-btn--destructive:hover:not(:disabled) {\n filter: brightness(0.92);\n}\n.cfi-vi .cfi-vi-icon-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n color: var(--cfi-color-gray-500, #6b7280);\n border-radius: var(--cfi-radius-sm, 4px);\n display: inline-flex;\n}\n.cfi-vi .cfi-vi-icon-btn:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-vi .cfi-vi-tag {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 1px 8px;\n border-radius: 999px;\n font-size: var(--cfi-font-size-xs, 11px);\n font-weight: 600;\n}\n.cfi-vi .cfi-vi-tag--default {\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi .cfi-vi-tag--outline {\n background: transparent;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi .cfi-vi-tag--secondary {\n background: var(--cfi-color-gray-200, #e5e7eb);\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi .cfi-vi-tag--success {\n background: #16a34a;\n color: #fff;\n}\n.cfi-vi .cfi-vi-tag--purple {\n background: var(--cfi-color-violet-600, #7c3aed);\n color: #fff;\n}\n.cfi-vi .cfi-vi-card {\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-lg, 8px);\n background: #fff;\n}\n.cfi-vi .cfi-vi-card--active {\n border-color: #86efac;\n background: #f0fdf4;\n}\n.cfi-vi .cfi-vi-card--hover:hover {\n border-color: var(--cfi-color-primary-600, #2563eb);\n}\n.cfi-vi .cfi-vi-card-head {\n padding: var(--cfi-spacing-md, 12px);\n padding-bottom: var(--cfi-spacing-sm, 8px);\n}\n.cfi-vi .cfi-vi-card-body {\n padding: 0 var(--cfi-spacing-md, 12px) var(--cfi-spacing-md, 12px);\n}\n.cfi-vi .cfi-vi-card-title {\n font-size: var(--cfi-font-size-base, 15px);\n font-weight: 600;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.cfi-vi .cfi-vi-link {\n background: none;\n border: none;\n padding: 0;\n color: inherit;\n font: inherit;\n cursor: pointer;\n text-align: left;\n}\n.cfi-vi .cfi-vi-link:hover {\n text-decoration: underline;\n}\n.cfi-vi .cfi-vi-field {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-xs, 4px);\n}\n.cfi-vi .cfi-vi-label {\n font-size: var(--cfi-font-size-sm, 12px);\n font-weight: 600;\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi .cfi-vi-hint {\n font-size: var(--cfi-font-size-xs, 11px);\n color: var(--cfi-color-gray-500, #6b7280);\n margin: 2px 0 0;\n}\n.cfi-vi .cfi-vi-input,\n.cfi-vi select.cfi-vi-input {\n padding: 6px 8px;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-md, 6px);\n background: #fff;\n font: inherit;\n color: inherit;\n width: 100%;\n}\n.cfi-vi .cfi-vi-input:focus {\n outline: 2px solid var(--cfi-color-primary-600, #2563eb);\n outline-offset: 1px;\n}\n.cfi-vi-modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 50;\n padding: 16px;\n}\n.cfi-vi-modal {\n background: #fff;\n border-radius: var(--cfi-radius-lg, 8px);\n width: 100%;\n max-width: 32rem;\n max-height: 90vh;\n overflow: auto;\n box-shadow: var(--cfi-shadow-lg, 0 10px 30px rgba(0,0,0,0.2));\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n color: var(--cfi-color-gray-900, #111827);\n display: flex;\n flex-direction: column;\n}\n.cfi-vi-modal-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--cfi-spacing-md, 14px);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-vi-modal-title {\n font-size: var(--cfi-font-size-lg, 16px);\n font-weight: 600;\n margin: 0;\n}\n.cfi-vi-modal-body {\n padding: var(--cfi-spacing-md, 14px);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 12px);\n}\n.cfi-vi-modal-foot {\n display: flex;\n justify-content: flex-end;\n gap: var(--cfi-spacing-sm, 8px);\n padding: var(--cfi-spacing-md, 14px);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-vi-icon-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n color: var(--cfi-color-gray-500, #6b7280);\n border-radius: 4px;\n display: inline-flex;\n}\n.cfi-vi .cfi-vi-spinner {\n display: inline-block;\n border: 2px solid var(--cfi-color-gray-300, #d1d5db);\n border-top-color: var(--cfi-color-primary-600, #2563eb);\n border-radius: 50%;\n animation: cfi-vi-spin 0.8s linear infinite;\n}\n.cfi-vi .cfi-vi-list {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 10px);\n}\n.cfi-vi .cfi-vi-list-head {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n}\n.cfi-vi .cfi-vi-h1 {\n font-size: var(--cfi-font-size-lg, 18px);\n font-weight: 600;\n margin: 0;\n}\n.cfi-vi .cfi-vi-active-line {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: var(--cfi-font-size-sm, 13px);\n color: var(--cfi-color-gray-600, #4b5563);\n margin-top: 2px;\n}\n.cfi-vi .cfi-vi-active-name {\n font-weight: 600;\n color: #15803d;\n}\n.cfi-vi .cfi-vi-active-extras {\n margin-top: var(--cfi-spacing-md, 16px);\n padding-top: var(--cfi-spacing-md, 16px);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 16px);\n}\n.cfi-vi-mapper {\n display: grid;\n grid-template-columns: 1fr;\n gap: var(--cfi-spacing-lg, 24px);\n align-items: start;\n}\n@media (min-width: 1024px) {\n .cfi-vi-mapper {\n grid-template-columns: 1fr 1fr;\n }\n}\n.cfi-vi-mapper .cfi-vi-mapper-col {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-lg, 24px);\n min-width: 0;\n}\n.cfi-vi-mapper .cfi-vi-mapper-section {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 8px);\n}\n.cfi-vi-mapper .cfi-vi-mapper-section-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n.cfi-vi-mapper .cfi-vi-mapper-h3 {\n font-size: var(--cfi-font-size-xs, 11px);\n font-weight: 700;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--cfi-color-gray-500, #6b7280);\n margin: 0;\n}\n.cfi-vi-mapper .cfi-vi-mapper-note {\n font-size: var(--cfi-font-size-xs, 11px);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-vi-mapper .cfi-vi-mapper-box {\n border: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n border-radius: var(--cfi-radius-lg, 8px);\n background: #fff;\n padding: var(--cfi-spacing-md, 14px);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.cfi-vi-mapper .cfi-vi-mapper-err {\n font-size: var(--cfi-font-size-xs, 11px);\n color: var(--cfi-color-error, #b91c1c);\n margin: 2px 0 0;\n}\n.cfi-vi-mapper .cfi-vi-mapper-save {\n display: flex;\n align-items: center;\n gap: 12px;\n padding-top: 4px;\n}\n.cfi-vi-mapper .cfi-vi-mapper-dirty {\n font-size: var(--cfi-font-size-xs, 11px);\n color: #b45309;\n}\n.cfi-vi-mapper .cfi-vi-hier-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.cfi-vi-mapper .cfi-vi-hier-elbow {\n width: 18px;\n align-self: stretch;\n border-left: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n height: 18px;\n margin-bottom: 9px;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-hier-dot {\n width: 14px;\n height: 14px;\n border-radius: 50%;\n border: 2px solid var(--cfi-color-gray-300, #d1d5db);\n background: #fff;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-hier-dot--filled {\n border-color: var(--cfi-color-primary-600, #6366f1);\n background: var(--cfi-color-primary-50, #eef2ff);\n}\n.cfi-vi-mapper .cfi-vi-hier-name {\n font-size: var(--cfi-font-size-xs, 12px);\n font-weight: 600;\n color: var(--cfi-color-gray-600, #4b5563);\n width: 96px;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-leaf {\n font-size: 10px;\n font-weight: 600;\n color: #b45309;\n background: #fffbeb;\n border: 1px solid #fde68a;\n padding: 1px 6px;\n border-radius: 999px;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-dropzone {\n flex: 1;\n min-height: 36px;\n border-radius: var(--cfi-radius-md, 6px);\n border: 2px solid;\n display: flex;\n align-items: center;\n padding: 0 10px;\n min-width: 0;\n transition: all 0.12s;\n}\n.cfi-vi-mapper .cfi-vi-dropzone--active {\n border-color: var(--cfi-color-primary-600, #6366f1);\n background: var(--cfi-color-primary-50, #eef2ff);\n}\n.cfi-vi-mapper .cfi-vi-dropzone--filled {\n border-style: solid;\n border-color: var(--cfi-color-gray-200, #e5e7eb);\n background: #fff;\n}\n.cfi-vi-mapper .cfi-vi-dropzone--empty {\n border-style: dashed;\n border-color: var(--cfi-color-gray-200, #e5e7eb);\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-vi-mapper .cfi-vi-dropzone--covered {\n border-style: solid;\n border-color: #a7f3d0;\n background: #ecfdf5;\n}\n.cfi-vi-mapper .cfi-vi-dropzone-ph {\n font-size: var(--cfi-font-size-xs, 12px);\n color: var(--cfi-color-gray-400, #9ca3af);\n user-select: none;\n}\n.cfi-vi-mapper .cfi-vi-base-hint {\n font-size: 10px;\n font-family: ui-monospace, monospace;\n color: #1d4ed8;\n background: #eff6ff;\n border: 1px solid #bfdbfe;\n padding: 1px 6px;\n border-radius: 4px;\n flex-shrink: 0;\n white-space: nowrap;\n}\n.cfi-vi-mapper .cfi-vi-auto-row {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n.cfi-vi-mapper .cfi-vi-auto-label {\n width: 160px;\n flex-shrink: 0;\n padding-top: 6px;\n}\n.cfi-vi-mapper .cfi-vi-auto-label-text {\n font-size: var(--cfi-font-size-xs, 12px);\n font-weight: 600;\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi-mapper .cfi-vi-auto-cover {\n font-size: 10px;\n margin: 2px 0 0;\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-vi-mapper .cfi-vi-auto-cover--on {\n color: #047857;\n}\n.cfi-vi-mapper .cfi-vi-auto-auto {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n min-width: 0;\n color: #047857;\n}\n.cfi-vi-mapper .cfi-vi-auto-auto-label {\n font-size: var(--cfi-font-size-xs, 12px);\n font-family: ui-monospace, monospace;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.cfi-vi-mapper .cfi-vi-auto-auto-tag {\n font-size: 10px;\n font-style: italic;\n color: #059669;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-auto-transform {\n width: 224px;\n flex-shrink: 0;\n padding-top: 6px;\n font-size: 11px;\n color: var(--cfi-color-gray-500, #6b7280);\n line-height: 1.3;\n}\n.cfi-vi-mapper .cfi-vi-auto-transform-label {\n font-weight: 600;\n}\n.cfi-vi-mapper .cfi-vi-pool-col {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 8px);\n}\n@media (min-width: 1024px) {\n .cfi-vi-mapper .cfi-vi-pool-col {\n position: sticky;\n top: 16px;\n align-self: start;\n }\n}\n.cfi-vi-mapper .cfi-vi-search {\n position: relative;\n}\n.cfi-vi-mapper .cfi-vi-search .cfi-vi-input {\n padding-left: 28px;\n}\n.cfi-vi-mapper .cfi-vi-search-icon {\n position: absolute;\n left: 8px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--cfi-color-gray-400, #9ca3af);\n pointer-events: none;\n}\n.cfi-vi-mapper .cfi-vi-pool {\n border: 2px dashed var(--cfi-color-gray-200, #e5e7eb);\n background: var(--cfi-color-gray-50, #f9fafb);\n border-radius: var(--cfi-radius-lg, 8px);\n padding: 12px;\n min-height: 200px;\n max-height: 600px;\n overflow-y: auto;\n}\n.cfi-vi-mapper .cfi-vi-pool--active {\n border-color: var(--cfi-color-primary-600, #818cf8);\n background: var(--cfi-color-primary-50, #eef2ff);\n}\n.cfi-vi-mapper .cfi-vi-pool-empty {\n font-size: var(--cfi-font-size-xs, 12px);\n color: var(--cfi-color-gray-400, #9ca3af);\n font-style: italic;\n}\n.cfi-vi-mapper .cfi-vi-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n.cfi-vi-mapper .cfi-vi-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: var(--cfi-radius-md, 6px);\n background: #fff;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n cursor: grab;\n user-select: none;\n font-size: var(--cfi-font-size-xs, 12px);\n font-family: ui-monospace, monospace;\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-vi-mapper .cfi-vi-chip:hover {\n border-color: var(--cfi-color-primary-600, #818cf8);\n background: var(--cfi-color-primary-50, #eef2ff);\n}\n.cfi-vi-mapper .cfi-vi-chip:active {\n cursor: grabbing;\n}\n.cfi-vi-mapper .cfi-vi-chip--assigned {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n min-width: 0;\n cursor: grab;\n}\n.cfi-vi-mapper .cfi-vi-chip--assigned:active {\n cursor: grabbing;\n}\n.cfi-vi-mapper .cfi-vi-chip-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--cfi-color-gray-400, #9ca3af);\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-chip-dot--on {\n background: var(--cfi-color-primary-600, #6366f1);\n}\n.cfi-vi-mapper .cfi-vi-chip-label {\n font-size: var(--cfi-font-size-xs, 12px);\n font-family: ui-monospace, monospace;\n color: #3730a3;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.cfi-vi-mapper .cfi-vi-chip-x {\n margin-left: 4px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n color: var(--cfi-color-gray-400, #9ca3af);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n.cfi-vi-mapper .cfi-vi-chip-x:hover {\n background: #fee2e2;\n color: #ef4444;\n}\n.cfi-vi .cfi-vi-spin {\n animation: cfi-vi-spin 0.8s linear infinite;\n}\n.cfi-vi .cfi-vi-detail {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-lg, 20px);\n}\n.cfi-vi .cfi-vi-h2 {\n font-size: var(--cfi-font-size-base, 15px);\n font-weight: 600;\n margin: 0;\n}\n.cfi-vi .cfi-vi-panel {\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-md, 6px);\n background: #fff;\n padding: var(--cfi-spacing-md, 16px);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 12px);\n}\n.cfi-vi .cfi-vi-grid2 {\n display: grid;\n grid-template-columns: 1fr;\n gap: var(--cfi-spacing-md, 16px);\n}\n@media (min-width: 768px) {\n .cfi-vi .cfi-vi-grid2 {\n grid-template-columns: 1fr 1fr;\n }\n}\n.cfi-vi .cfi-vi-lock {\n display: flex;\n align-items: center;\n gap: 8px;\n border: 1px solid #fde68a;\n background: #fffbeb;\n color: #92400e;\n border-radius: var(--cfi-radius-md, 6px);\n padding: 8px 12px;\n font-size: var(--cfi-font-size-xs, 12px);\n}\n.cfi-vi .cfi-vi-table {\n width: 100%;\n border-collapse: collapse;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-md, 6px);\n font-size: var(--cfi-font-size-sm, 13px);\n}\n.cfi-vi .cfi-vi-table th,\n.cfi-vi .cfi-vi-table td {\n text-align: left;\n padding: 6px 10px;\n border-bottom: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n vertical-align: middle;\n}\n.cfi-vi .cfi-vi-table th {\n font-size: var(--cfi-font-size-xs, 11px);\n font-weight: 600;\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-vi .cfi-vi-table tr:last-child td {\n border-bottom: none;\n}\n.cfi-vi .cfi-vi-danger {\n border: 1px solid rgba(220, 38, 38, 0.4);\n background: rgba(220, 38, 38, 0.05);\n border-radius: var(--cfi-radius-md, 6px);\n padding: var(--cfi-spacing-md, 16px);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 12px);\n}\n.cfi-vi .cfi-vi-aliases {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 12px);\n}\n.cfi-vi .cfi-vi-alias-rows {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.cfi-vi .cfi-vi-tag--warn {\n background: #fffbeb;\n color: #92400e;\n border: 1px solid #fde68a;\n}\n.cfi-vi .cfi-vi-tag--danger {\n background: #fef2f2;\n color: #b91c1c;\n border: 1px solid #fecaca;\n}\n.cfi-vi .cfi-vi-select {\n padding: 6px 8px;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-md, 6px);\n background: #fff;\n font: inherit;\n}\n.cfi-vi .cfi-vi-select:focus {\n outline: 2px solid var(--cfi-color-primary-600, #2563eb);\n outline-offset: -1px;\n}\n.cfi-vi .cfi-vi-file {\n font: inherit;\n}\n.cfi-vi .cfi-vi-alert {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: var(--cfi-radius-md, 6px);\n font-size: var(--cfi-font-size-sm, 13px);\n margin: 8px 0;\n}\n.cfi-vi .cfi-vi-alert--error {\n background: #fef2f2;\n color: #b91c1c;\n}\n.cfi-vi .cfi-vi-alert--warn {\n background: #fffbeb;\n color: #92400e;\n}\n.cfi-vi .cfi-vi-alert ul.cfi-vi-blockers {\n margin: 0;\n padding-left: 18px;\n}\n.cfi-vi .cfi-vi-loading {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--cfi-color-gray-500, #6b7280);\n padding: 12px 0;\n}\n.cfi-vi .cfi-vi-files-head {\n align-items: center;\n margin-bottom: 12px;\n}\n.cfi-vi .cfi-vi-files-title {\n font-size: var(--cfi-font-size-lg, 18px);\n font-weight: 600;\n margin: 0;\n}\n.cfi-vi .cfi-vi-files-filters {\n gap: 8px;\n align-items: center;\n margin-bottom: 12px;\n}\n.cfi-vi .cfi-vi-files-table th,\n.cfi-vi .cfi-vi-files-table td {\n white-space: nowrap;\n}\n.cfi-vi .cfi-vi-files-file {\n font-family: var(--cfi-font-mono, ui-monospace, monospace);\n max-width: 220px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.cfi-vi .cfi-vi-files-actions {\n display: flex;\n gap: 4px;\n justify-content: flex-end;\n}\n.cfi-vi .cfi-vi-files-detail td {\n background: var(--cfi-color-gray-50, #f9fafb);\n white-space: normal;\n}\n.cfi-vi .cfi-vi-files-pager {\n align-items: center;\n gap: 10px;\n margin-top: 12px;\n}\n.cfi-vi .cfi-vi-ta-right {\n text-align: right;\n}\n.cfi-vi .cfi-vi-danger-text {\n color: #b91c1c;\n}\n");
|
|
29
29
|
|
|
30
30
|
// src/VolumeImport.tsx
|
|
31
31
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -271,9 +271,9 @@ function UploadStatusPanel(props) {
|
|
|
271
271
|
] });
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
-
// src/
|
|
275
|
-
import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
|
|
276
|
-
import {
|
|
274
|
+
// src/VolumeFiles.tsx
|
|
275
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
|
|
276
|
+
import { AlertTriangle as AlertTriangle2, Download, RotateCcw as RotateCcw2, FileUp as FileUp2, ChevronRight, ChevronDown } from "lucide-react";
|
|
277
277
|
|
|
278
278
|
// src/ui.tsx
|
|
279
279
|
import { X } from "lucide-react";
|
|
@@ -310,6 +310,9 @@ function TextInput(props) {
|
|
|
310
310
|
const { className, ...rest } = props;
|
|
311
311
|
return /* @__PURE__ */ jsx2("input", { className: className ? `cfi-vi-input ${className}` : "cfi-vi-input", ...rest });
|
|
312
312
|
}
|
|
313
|
+
function Spinner(props) {
|
|
314
|
+
return /* @__PURE__ */ jsx2("span", { className: "cfi-vi-spinner", style: { width: props.size ?? 14, height: props.size ?? 14 }, "aria-hidden": true });
|
|
315
|
+
}
|
|
313
316
|
function Modal(props) {
|
|
314
317
|
if (!props.open) return null;
|
|
315
318
|
return /* @__PURE__ */ jsx2("div", { className: "cfi-vi-modal-overlay", role: "dialog", "aria-modal": "true", onClick: props.onClose, children: /* @__PURE__ */ jsxs2("div", { className: "cfi-vi-modal", onClick: (e) => e.stopPropagation(), children: [
|
|
@@ -322,23 +325,469 @@ function Modal(props) {
|
|
|
322
325
|
] }) });
|
|
323
326
|
}
|
|
324
327
|
|
|
325
|
-
// src/
|
|
328
|
+
// src/VolumeFiles.tsx
|
|
326
329
|
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
327
|
-
var
|
|
328
|
-
|
|
330
|
+
var MONTH_NAMES2 = [
|
|
331
|
+
"January",
|
|
332
|
+
"February",
|
|
333
|
+
"March",
|
|
334
|
+
"April",
|
|
335
|
+
"May",
|
|
336
|
+
"June",
|
|
337
|
+
"July",
|
|
338
|
+
"August",
|
|
339
|
+
"September",
|
|
340
|
+
"October",
|
|
341
|
+
"November",
|
|
342
|
+
"December"
|
|
343
|
+
];
|
|
344
|
+
var MONTH_ABBR = MONTH_NAMES2.map((m) => m.slice(0, 3));
|
|
345
|
+
var CURRENT_YEAR = (/* @__PURE__ */ new Date()).getFullYear();
|
|
346
|
+
var CURRENT_MONTH = (/* @__PURE__ */ new Date()).getMonth() + 1;
|
|
347
|
+
var YEAR_OPTIONS = [CURRENT_YEAR - 2, CURRENT_YEAR - 1, CURRENT_YEAR, CURRENT_YEAR + 1, CURRENT_YEAR + 2];
|
|
348
|
+
var ACTIVE_STATUSES = /* @__PURE__ */ new Set(["pending", "processing", "awaiting_calendar"]);
|
|
349
|
+
var POLL_INTERVAL_MS = 3e3;
|
|
350
|
+
var PAGE_SIZE = 20;
|
|
351
|
+
var STATUS_LABELS2 = {
|
|
352
|
+
awaiting_calendar: "awaiting calendar",
|
|
353
|
+
done_with_errors: "done with errors"
|
|
354
|
+
};
|
|
355
|
+
function statusTagClass(status) {
|
|
356
|
+
switch (status) {
|
|
357
|
+
case "done":
|
|
358
|
+
return "cfi-vi-tag--success";
|
|
359
|
+
case "done_with_errors":
|
|
360
|
+
return "cfi-vi-tag--warn";
|
|
361
|
+
case "awaiting_calendar":
|
|
362
|
+
return "cfi-vi-tag--warn";
|
|
363
|
+
case "failed":
|
|
364
|
+
return "cfi-vi-tag--danger";
|
|
365
|
+
case "processing":
|
|
366
|
+
return "cfi-vi-tag--secondary";
|
|
367
|
+
default:
|
|
368
|
+
return "cfi-vi-tag--default";
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function computeCutoffLabel(uploadYear, uploadMonth, lag) {
|
|
372
|
+
let cutoffMonth = uploadMonth - lag;
|
|
373
|
+
let cutoffYear = uploadYear;
|
|
374
|
+
while (cutoffMonth <= 0) {
|
|
375
|
+
cutoffMonth += 12;
|
|
376
|
+
cutoffYear--;
|
|
377
|
+
}
|
|
378
|
+
let predMonth = cutoffMonth + 1;
|
|
379
|
+
let predYear = cutoffYear;
|
|
380
|
+
if (predMonth > 12) {
|
|
381
|
+
predMonth -= 12;
|
|
382
|
+
predYear++;
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
cutoffLabel: `${MONTH_NAMES2[cutoffMonth - 1]} ${cutoffYear}`,
|
|
386
|
+
predictionsLabel: `${MONTH_NAMES2[predMonth - 1]} ${predYear}`
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function formatDuration(startedAt, completedAt) {
|
|
390
|
+
if (!startedAt || !completedAt) return "\u2014";
|
|
391
|
+
const ms = new Date(completedAt).getTime() - new Date(startedAt).getTime();
|
|
392
|
+
const totalSec = Math.max(0, Math.floor(ms / 1e3));
|
|
393
|
+
const m = Math.floor(totalSec / 60);
|
|
394
|
+
const s = totalSec % 60;
|
|
395
|
+
return m > 0 ? `${m}m ${s}s` : `${s}s`;
|
|
396
|
+
}
|
|
397
|
+
function UploadDialog(props) {
|
|
398
|
+
const { transport, sources, activeSourceId, calendarSeeded, onClose, onCreated } = props;
|
|
399
|
+
const [selectedSourceId, setSelectedSourceId] = useState2(activeSourceId ?? sources[0]?.id ?? "");
|
|
400
|
+
const [year, setYear] = useState2(CURRENT_YEAR);
|
|
401
|
+
const [month, setMonth] = useState2(CURRENT_MONTH);
|
|
402
|
+
const [lag, setLag] = useState2(1);
|
|
403
|
+
const [file, setFile] = useState2(null);
|
|
404
|
+
const [submitting, setSubmitting] = useState2(false);
|
|
405
|
+
const [error, setError] = useState2(null);
|
|
406
|
+
const [hierarchyMapped, setHierarchyMapped] = useState2(null);
|
|
407
|
+
const selected = sources.find((s) => s.id === selectedSourceId) ?? null;
|
|
408
|
+
const isTall = selected?.layout === "tall";
|
|
409
|
+
useEffect2(() => {
|
|
410
|
+
if (!selectedSourceId) {
|
|
411
|
+
setHierarchyMapped(null);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
let cancelled = false;
|
|
415
|
+
setHierarchyMapped(null);
|
|
416
|
+
transport.isHierarchyMapped(selectedSourceId).then((m) => {
|
|
417
|
+
if (!cancelled) setHierarchyMapped(m);
|
|
418
|
+
}).catch(() => {
|
|
419
|
+
if (!cancelled) setHierarchyMapped(false);
|
|
420
|
+
});
|
|
421
|
+
return () => {
|
|
422
|
+
cancelled = true;
|
|
423
|
+
};
|
|
424
|
+
}, [selectedSourceId, transport]);
|
|
425
|
+
const blockers = [];
|
|
426
|
+
if (!selected) blockers.push("Pick a source to upload to");
|
|
427
|
+
else {
|
|
428
|
+
if (!isTall && !selected.uniqueKeySegmentId) blockers.push("Source has no unique-key column set");
|
|
429
|
+
if (hierarchyMapped === false) blockers.push("Hierarchy levels not mapped");
|
|
430
|
+
}
|
|
431
|
+
if (calendarSeeded === false) blockers.push("Calendar not seeded");
|
|
432
|
+
const blocked = blockers.length > 0;
|
|
433
|
+
const { cutoffLabel, predictionsLabel } = computeCutoffLabel(year, month, lag);
|
|
434
|
+
const handleSubmit = useCallback2(async () => {
|
|
435
|
+
if (!selected || !file) {
|
|
436
|
+
setError("Pick a source and file first");
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
setSubmitting(true);
|
|
440
|
+
setError(null);
|
|
441
|
+
try {
|
|
442
|
+
const input = {
|
|
443
|
+
sourceId: selected.id,
|
|
444
|
+
file,
|
|
445
|
+
...isTall ? {} : { uploadYear: year, uploadMonth: month, actualsLagMonths: lag }
|
|
446
|
+
};
|
|
447
|
+
const created = await transport.createUpload(input);
|
|
448
|
+
onCreated(created);
|
|
449
|
+
} catch (e) {
|
|
450
|
+
setError(e instanceof Error ? e.message : "Upload failed");
|
|
451
|
+
} finally {
|
|
452
|
+
setSubmitting(false);
|
|
453
|
+
}
|
|
454
|
+
}, [selected, file, isTall, year, month, lag, transport, onCreated]);
|
|
455
|
+
return /* @__PURE__ */ jsx3("div", { className: "cfi-vi-modal-overlay", role: "dialog", "aria-modal": "true", onClick: onClose, children: /* @__PURE__ */ jsxs3("div", { className: "cfi-vi-modal", onClick: (e) => e.stopPropagation(), children: [
|
|
456
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-modal-head", children: [
|
|
457
|
+
/* @__PURE__ */ jsx3("h2", { className: "cfi-vi-modal-title", children: "Upload volume file" }),
|
|
458
|
+
/* @__PURE__ */ jsx3("button", { type: "button", className: "cfi-vi-icon-btn", "aria-label": "Close", onClick: onClose, children: "\u2715" })
|
|
459
|
+
] }),
|
|
460
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-modal-body", children: [
|
|
461
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-field", children: [
|
|
462
|
+
/* @__PURE__ */ jsx3("label", { className: "cfi-vi-label", htmlFor: "cfi-vf-source", children: "Source" }),
|
|
463
|
+
/* @__PURE__ */ jsxs3(
|
|
464
|
+
"select",
|
|
465
|
+
{
|
|
466
|
+
id: "cfi-vf-source",
|
|
467
|
+
className: "cfi-vi-select",
|
|
468
|
+
value: selectedSourceId,
|
|
469
|
+
onChange: (e) => setSelectedSourceId(e.target.value),
|
|
470
|
+
children: [
|
|
471
|
+
sources.length === 0 && /* @__PURE__ */ jsx3("option", { value: "", children: "No sources defined" }),
|
|
472
|
+
sources.slice().sort((a, b) => a.name.localeCompare(b.name)).map((s) => /* @__PURE__ */ jsxs3("option", { value: s.id, children: [
|
|
473
|
+
s.name,
|
|
474
|
+
" (",
|
|
475
|
+
s.code,
|
|
476
|
+
") \xB7 ",
|
|
477
|
+
s.layout,
|
|
478
|
+
s.kind === "overlay" ? " \xB7 overlay" : ""
|
|
479
|
+
] }, s.id))
|
|
480
|
+
]
|
|
481
|
+
}
|
|
482
|
+
)
|
|
483
|
+
] }),
|
|
484
|
+
blockers.length > 0 && /* @__PURE__ */ jsxs3("div", { className: "cfi-vi-alert cfi-vi-alert--warn", children: [
|
|
485
|
+
/* @__PURE__ */ jsx3(AlertTriangle2, { size: 16, "aria-hidden": true }),
|
|
486
|
+
/* @__PURE__ */ jsx3("ul", { className: "cfi-vi-blockers", children: blockers.map((b, i) => /* @__PURE__ */ jsx3("li", { children: b }, i)) })
|
|
487
|
+
] }),
|
|
488
|
+
selected && !isTall && /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
489
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-row", children: [
|
|
490
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-field", children: [
|
|
491
|
+
/* @__PURE__ */ jsx3("label", { className: "cfi-vi-label", htmlFor: "cfi-vf-year", children: "Year" }),
|
|
492
|
+
/* @__PURE__ */ jsx3("select", { id: "cfi-vf-year", className: "cfi-vi-select", value: year, onChange: (e) => setYear(Number(e.target.value)), children: YEAR_OPTIONS.map((y) => /* @__PURE__ */ jsx3("option", { value: y, children: y }, y)) })
|
|
493
|
+
] }),
|
|
494
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-field", children: [
|
|
495
|
+
/* @__PURE__ */ jsx3("label", { className: "cfi-vi-label", htmlFor: "cfi-vf-month", children: "Month" }),
|
|
496
|
+
/* @__PURE__ */ jsx3("select", { id: "cfi-vf-month", className: "cfi-vi-select", value: month, onChange: (e) => setMonth(Number(e.target.value)), children: MONTH_NAMES2.map((name, i) => /* @__PURE__ */ jsx3("option", { value: i + 1, children: name }, name)) })
|
|
497
|
+
] }),
|
|
498
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-field", children: [
|
|
499
|
+
/* @__PURE__ */ jsx3("label", { className: "cfi-vi-label", htmlFor: "cfi-vf-lag", children: "Actuals lag (months)" }),
|
|
500
|
+
/* @__PURE__ */ jsx3("select", { id: "cfi-vf-lag", className: "cfi-vi-select", value: lag, onChange: (e) => setLag(Number(e.target.value)), children: [0, 1, 2, 3, 4, 5, 6].map((n) => /* @__PURE__ */ jsxs3("option", { value: n, children: [
|
|
501
|
+
n,
|
|
502
|
+
" month",
|
|
503
|
+
n !== 1 ? "s" : ""
|
|
504
|
+
] }, n)) })
|
|
505
|
+
] })
|
|
506
|
+
] }),
|
|
507
|
+
/* @__PURE__ */ jsxs3("p", { className: "cfi-vi-hint", children: [
|
|
508
|
+
"\u2190 Actuals up to ",
|
|
509
|
+
cutoffLabel,
|
|
510
|
+
" \xB7 Predictions \u2192 from ",
|
|
511
|
+
predictionsLabel
|
|
512
|
+
] })
|
|
513
|
+
] }),
|
|
514
|
+
selected && isTall && /* @__PURE__ */ jsx3("p", { className: "cfi-vi-hint", children: "Tall-format upload \u2014 each row carries its own Week Ending date; cutoff fields aren\u2019t needed." }),
|
|
515
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-field", children: [
|
|
516
|
+
/* @__PURE__ */ jsx3("label", { className: "cfi-vi-label", htmlFor: "cfi-vf-file", children: "File (.xlsx / .xls)" }),
|
|
517
|
+
/* @__PURE__ */ jsx3(
|
|
518
|
+
"input",
|
|
519
|
+
{
|
|
520
|
+
id: "cfi-vf-file",
|
|
521
|
+
type: "file",
|
|
522
|
+
accept: ".xlsx,.xls",
|
|
523
|
+
className: "cfi-vi-file",
|
|
524
|
+
onChange: (e) => setFile(e.target.files?.[0] ?? null)
|
|
525
|
+
}
|
|
526
|
+
)
|
|
527
|
+
] }),
|
|
528
|
+
error && /* @__PURE__ */ jsxs3("div", { className: "cfi-vi-alert cfi-vi-alert--error", children: [
|
|
529
|
+
/* @__PURE__ */ jsx3(AlertTriangle2, { size: 16, "aria-hidden": true }),
|
|
530
|
+
" ",
|
|
531
|
+
/* @__PURE__ */ jsx3("span", { children: error })
|
|
532
|
+
] })
|
|
533
|
+
] }),
|
|
534
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-modal-foot", children: [
|
|
535
|
+
/* @__PURE__ */ jsx3(Btn, { variant: "outline", size: "sm", onClick: onClose, children: "Cancel" }),
|
|
536
|
+
/* @__PURE__ */ jsxs3(Btn, { size: "sm", disabled: submitting || blocked || !file, onClick: handleSubmit, children: [
|
|
537
|
+
submitting ? /* @__PURE__ */ jsx3(Spinner, {}) : /* @__PURE__ */ jsx3(FileUp2, { size: 14, "aria-hidden": true }),
|
|
538
|
+
" ",
|
|
539
|
+
submitting ? "Uploading\u2026" : "Upload"
|
|
540
|
+
] })
|
|
541
|
+
] })
|
|
542
|
+
] }) });
|
|
543
|
+
}
|
|
544
|
+
function VolumeFiles({ transport, className }) {
|
|
329
545
|
const [sources, setSources] = useState2([]);
|
|
330
546
|
const [activeSourceId, setActiveSourceId] = useState2(null);
|
|
331
|
-
const [
|
|
547
|
+
const [calendarSeeded, setCalendarSeeded] = useState2(null);
|
|
548
|
+
const [uploads, setUploads] = useState2([]);
|
|
549
|
+
const [total, setTotal] = useState2(0);
|
|
332
550
|
const [loading, setLoading] = useState2(true);
|
|
333
551
|
const [error, setError] = useState2(null);
|
|
334
|
-
const [
|
|
335
|
-
const [
|
|
336
|
-
const [
|
|
337
|
-
const [
|
|
338
|
-
const [
|
|
339
|
-
const [
|
|
340
|
-
const
|
|
341
|
-
|
|
552
|
+
const [dialogOpen, setDialogOpen] = useState2(false);
|
|
553
|
+
const [filterStatus, setFilterStatus] = useState2("");
|
|
554
|
+
const [filterSourceId, setFilterSourceId] = useState2("");
|
|
555
|
+
const [offset, setOffset] = useState2(0);
|
|
556
|
+
const [expandedId, setExpandedId] = useState2(null);
|
|
557
|
+
const [errorsById, setErrorsById] = useState2({});
|
|
558
|
+
const load = useCallback2(async (opts) => {
|
|
559
|
+
if (!opts?.silent) setLoading(true);
|
|
560
|
+
try {
|
|
561
|
+
const [srcs, activeId, result, calSeeded] = await Promise.all([
|
|
562
|
+
transport.listSources(),
|
|
563
|
+
transport.getActiveSourceId().catch(() => null),
|
|
564
|
+
transport.listUploads({
|
|
565
|
+
limit: PAGE_SIZE,
|
|
566
|
+
offset,
|
|
567
|
+
...filterStatus ? { status: filterStatus } : {},
|
|
568
|
+
...filterSourceId ? { sourceId: filterSourceId } : {}
|
|
569
|
+
}),
|
|
570
|
+
transport.isCalendarSeeded ? transport.isCalendarSeeded().catch(() => null) : Promise.resolve(null)
|
|
571
|
+
]);
|
|
572
|
+
setSources(srcs);
|
|
573
|
+
setActiveSourceId(activeId);
|
|
574
|
+
setUploads(result.items);
|
|
575
|
+
setTotal(result.total);
|
|
576
|
+
setCalendarSeeded(calSeeded);
|
|
577
|
+
setError(null);
|
|
578
|
+
} catch (e) {
|
|
579
|
+
setError(e instanceof Error ? e.message : "Failed to load uploads");
|
|
580
|
+
} finally {
|
|
581
|
+
setLoading(false);
|
|
582
|
+
}
|
|
583
|
+
}, [transport, offset, filterStatus, filterSourceId]);
|
|
584
|
+
useEffect2(() => {
|
|
585
|
+
void load();
|
|
586
|
+
}, [load]);
|
|
587
|
+
useEffect2(() => {
|
|
588
|
+
const activeIds = uploads.filter((u) => ACTIVE_STATUSES.has(u.status)).map((u) => u.id);
|
|
589
|
+
if (activeIds.length === 0) return;
|
|
590
|
+
const timer = setInterval(async () => {
|
|
591
|
+
const updated = await Promise.allSettled(activeIds.map((id) => transport.getUpload(id)));
|
|
592
|
+
setUploads((prev) => prev.map((u) => {
|
|
593
|
+
const idx = activeIds.indexOf(u.id);
|
|
594
|
+
if (idx < 0) return u;
|
|
595
|
+
const res = updated[idx];
|
|
596
|
+
return res.status === "fulfilled" ? res.value : u;
|
|
597
|
+
}));
|
|
598
|
+
}, POLL_INTERVAL_MS);
|
|
599
|
+
return () => clearInterval(timer);
|
|
600
|
+
}, [uploads, transport]);
|
|
601
|
+
const handleCreated = useCallback2((u) => {
|
|
602
|
+
setDialogOpen(false);
|
|
603
|
+
setUploads((prev) => [u, ...prev.filter((x) => x.id !== u.id)]);
|
|
604
|
+
setTotal((n) => n + 1);
|
|
605
|
+
}, []);
|
|
606
|
+
const handleReprocess = useCallback2(async (id) => {
|
|
607
|
+
try {
|
|
608
|
+
await transport.reprocessUpload(id);
|
|
609
|
+
await load({ silent: true });
|
|
610
|
+
} catch (e) {
|
|
611
|
+
setError(e instanceof Error ? e.message : "Reprocess failed");
|
|
612
|
+
}
|
|
613
|
+
}, [transport, load]);
|
|
614
|
+
const handleDownload = useCallback2(async (id) => {
|
|
615
|
+
try {
|
|
616
|
+
const url = await transport.getUploadDownloadUrl(id);
|
|
617
|
+
window.open(url, "_blank", "noopener");
|
|
618
|
+
} catch (e) {
|
|
619
|
+
setError(e instanceof Error ? e.message : "Download failed");
|
|
620
|
+
}
|
|
621
|
+
}, [transport]);
|
|
622
|
+
const toggleExpand = useCallback2(async (u) => {
|
|
623
|
+
if (expandedId === u.id) {
|
|
624
|
+
setExpandedId(null);
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
setExpandedId(u.id);
|
|
628
|
+
if (!errorsById[u.id] && u.rowsFailed > 0) {
|
|
629
|
+
try {
|
|
630
|
+
const res = await transport.getUploadErrors(u.id, { limit: 100 });
|
|
631
|
+
setErrorsById((prev) => ({ ...prev, [u.id]: res.items }));
|
|
632
|
+
} catch {
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}, [expandedId, errorsById, transport]);
|
|
636
|
+
const totalPages = Math.ceil(total / PAGE_SIZE);
|
|
637
|
+
const currentPage = Math.floor(offset / PAGE_SIZE) + 1;
|
|
638
|
+
const dialogSources = useMemo2(() => sources, [sources]);
|
|
639
|
+
return /* @__PURE__ */ jsxs3(Root, { className, children: [
|
|
640
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-row cfi-vi-row--between cfi-vi-files-head", children: [
|
|
641
|
+
/* @__PURE__ */ jsx3("h2", { className: "cfi-vi-files-title", children: "Volume uploads" }),
|
|
642
|
+
/* @__PURE__ */ jsxs3(Btn, { size: "sm", onClick: () => setDialogOpen(true), children: [
|
|
643
|
+
/* @__PURE__ */ jsx3(FileUp2, { size: 14, "aria-hidden": true }),
|
|
644
|
+
" Upload file"
|
|
645
|
+
] })
|
|
646
|
+
] }),
|
|
647
|
+
error && /* @__PURE__ */ jsxs3("div", { className: "cfi-vi-alert cfi-vi-alert--error", children: [
|
|
648
|
+
/* @__PURE__ */ jsx3(AlertTriangle2, { size: 16, "aria-hidden": true }),
|
|
649
|
+
" ",
|
|
650
|
+
/* @__PURE__ */ jsx3("span", { children: error })
|
|
651
|
+
] }),
|
|
652
|
+
/* @__PURE__ */ jsxs3("div", { className: "cfi-vi-row cfi-vi-files-filters", children: [
|
|
653
|
+
/* @__PURE__ */ jsxs3("select", { className: "cfi-vi-select", value: filterSourceId, onChange: (e) => {
|
|
654
|
+
setFilterSourceId(e.target.value);
|
|
655
|
+
setOffset(0);
|
|
656
|
+
}, children: [
|
|
657
|
+
/* @__PURE__ */ jsx3("option", { value: "", children: "All sources" }),
|
|
658
|
+
sources.map((s) => /* @__PURE__ */ jsx3("option", { value: s.id, children: s.code }, s.id))
|
|
659
|
+
] }),
|
|
660
|
+
/* @__PURE__ */ jsxs3("select", { className: "cfi-vi-select", value: filterStatus, onChange: (e) => {
|
|
661
|
+
setFilterStatus(e.target.value);
|
|
662
|
+
setOffset(0);
|
|
663
|
+
}, children: [
|
|
664
|
+
/* @__PURE__ */ jsx3("option", { value: "", children: "All statuses" }),
|
|
665
|
+
/* @__PURE__ */ jsx3("option", { value: "pending", children: "Pending" }),
|
|
666
|
+
/* @__PURE__ */ jsx3("option", { value: "processing", children: "Processing" }),
|
|
667
|
+
/* @__PURE__ */ jsx3("option", { value: "done", children: "Done" }),
|
|
668
|
+
/* @__PURE__ */ jsx3("option", { value: "done_with_errors", children: "Done with errors" }),
|
|
669
|
+
/* @__PURE__ */ jsx3("option", { value: "failed", children: "Failed" })
|
|
670
|
+
] }),
|
|
671
|
+
/* @__PURE__ */ jsx3(Btn, { variant: "ghost", size: "sm", onClick: () => void load(), children: "Refresh" })
|
|
672
|
+
] }),
|
|
673
|
+
loading ? /* @__PURE__ */ jsxs3("div", { className: "cfi-vi-loading", children: [
|
|
674
|
+
/* @__PURE__ */ jsx3(Spinner, {}),
|
|
675
|
+
" Loading\u2026"
|
|
676
|
+
] }) : uploads.length === 0 ? /* @__PURE__ */ jsx3("p", { className: "cfi-vi-muted", children: "No uploads yet." }) : /* @__PURE__ */ jsxs3("table", { className: "cfi-vi-table cfi-vi-files-table", children: [
|
|
677
|
+
/* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsxs3("tr", { children: [
|
|
678
|
+
/* @__PURE__ */ jsx3("th", {}),
|
|
679
|
+
/* @__PURE__ */ jsx3("th", { children: "File" }),
|
|
680
|
+
/* @__PURE__ */ jsx3("th", { children: "Period" }),
|
|
681
|
+
/* @__PURE__ */ jsx3("th", { children: "Source" }),
|
|
682
|
+
/* @__PURE__ */ jsx3("th", { children: "Progress" }),
|
|
683
|
+
/* @__PURE__ */ jsx3("th", { children: "Catalogue" }),
|
|
684
|
+
/* @__PURE__ */ jsx3("th", { children: "Status" }),
|
|
685
|
+
/* @__PURE__ */ jsx3("th", { children: "Duration" }),
|
|
686
|
+
/* @__PURE__ */ jsx3("th", { className: "cfi-vi-ta-right", children: "Actions" })
|
|
687
|
+
] }) }),
|
|
688
|
+
/* @__PURE__ */ jsx3("tbody", { children: uploads.map((u) => {
|
|
689
|
+
const active = ACTIVE_STATUSES.has(u.status);
|
|
690
|
+
const expanded = expandedId === u.id;
|
|
691
|
+
const catalogue = u.rowsCanonicalised + u.rowsQueued + u.rowsBound;
|
|
692
|
+
return /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
693
|
+
/* @__PURE__ */ jsxs3("tr", { children: [
|
|
694
|
+
/* @__PURE__ */ jsx3("td", { children: /* @__PURE__ */ jsx3("button", { type: "button", className: "cfi-vi-icon-btn", "aria-label": "Toggle details", onClick: () => void toggleExpand(u), children: expanded ? /* @__PURE__ */ jsx3(ChevronDown, { size: 14 }) : /* @__PURE__ */ jsx3(ChevronRight, { size: 14 }) }) }),
|
|
695
|
+
/* @__PURE__ */ jsx3("td", { className: "cfi-vi-files-file", title: u.fileName, children: u.fileName }),
|
|
696
|
+
/* @__PURE__ */ jsxs3("td", { className: "cfi-vi-muted", children: [
|
|
697
|
+
u.uploadYear,
|
|
698
|
+
" / ",
|
|
699
|
+
MONTH_ABBR[u.uploadMonth - 1]
|
|
700
|
+
] }),
|
|
701
|
+
/* @__PURE__ */ jsx3("td", { children: /* @__PURE__ */ jsx3("span", { className: "cfi-vi-tag cfi-vi-tag--outline", children: u.source.code }) }),
|
|
702
|
+
/* @__PURE__ */ jsx3("td", { children: active ? /* @__PURE__ */ jsx3("span", { className: "cfi-vi-muted", children: "processing\u2026" }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
703
|
+
u.rowsProcessed.toLocaleString(),
|
|
704
|
+
" / ",
|
|
705
|
+
u.rowsTotal.toLocaleString(),
|
|
706
|
+
u.rowsFailed > 0 && /* @__PURE__ */ jsxs3("span", { className: "cfi-vi-danger-text", children: [
|
|
707
|
+
" (",
|
|
708
|
+
u.rowsFailed,
|
|
709
|
+
" failed)"
|
|
710
|
+
] })
|
|
711
|
+
] }) }),
|
|
712
|
+
/* @__PURE__ */ jsx3("td", { className: "cfi-vi-muted", children: catalogue === 0 ? "\u2014" : `${u.rowsCanonicalised}\u2713 \xB7 ${u.rowsQueued}\u23F3 \xB7 ${u.rowsBound}\u{1F517}` }),
|
|
713
|
+
/* @__PURE__ */ jsx3("td", { children: /* @__PURE__ */ jsxs3("span", { className: `cfi-vi-tag ${statusTagClass(u.status)}`, children: [
|
|
714
|
+
active && /* @__PURE__ */ jsx3(Spinner, { size: 10 }),
|
|
715
|
+
" ",
|
|
716
|
+
STATUS_LABELS2[u.status] ?? u.status.replace(/_/g, " ")
|
|
717
|
+
] }) }),
|
|
718
|
+
/* @__PURE__ */ jsx3("td", { className: "cfi-vi-muted", children: formatDuration(u.startedAt, u.completedAt) }),
|
|
719
|
+
/* @__PURE__ */ jsx3("td", { className: "cfi-vi-ta-right", children: /* @__PURE__ */ jsxs3("div", { className: "cfi-vi-files-actions", children: [
|
|
720
|
+
/* @__PURE__ */ jsx3("button", { type: "button", className: "cfi-vi-icon-btn", title: "Download original", onClick: () => void handleDownload(u.id), children: /* @__PURE__ */ jsx3(Download, { size: 14 }) }),
|
|
721
|
+
u.status === "failed" && /* @__PURE__ */ jsx3("button", { type: "button", className: "cfi-vi-icon-btn", title: "Reprocess", onClick: () => void handleReprocess(u.id), children: /* @__PURE__ */ jsx3(RotateCcw2, { size: 14 }) })
|
|
722
|
+
] }) })
|
|
723
|
+
] }, u.id),
|
|
724
|
+
expanded && /* @__PURE__ */ jsxs3("tr", { className: "cfi-vi-files-detail", children: [
|
|
725
|
+
/* @__PURE__ */ jsx3("td", {}),
|
|
726
|
+
/* @__PURE__ */ jsxs3("td", { colSpan: 8, children: [
|
|
727
|
+
u.errorSummary && /* @__PURE__ */ jsx3("p", { className: "cfi-vi-danger-text", children: u.errorSummary }),
|
|
728
|
+
u.rowsFailed === 0 ? /* @__PURE__ */ jsx3("p", { className: "cfi-vi-muted", children: "No row errors." }) : errorsById[u.id]?.length ? /* @__PURE__ */ jsxs3("table", { className: "cfi-vi-errors", children: [
|
|
729
|
+
/* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsxs3("tr", { children: [
|
|
730
|
+
/* @__PURE__ */ jsx3("th", { children: "Row" }),
|
|
731
|
+
/* @__PURE__ */ jsx3("th", { children: "Type" }),
|
|
732
|
+
/* @__PURE__ */ jsx3("th", { children: "Message" })
|
|
733
|
+
] }) }),
|
|
734
|
+
/* @__PURE__ */ jsx3("tbody", { children: errorsById[u.id].map((e, i) => /* @__PURE__ */ jsxs3("tr", { children: [
|
|
735
|
+
/* @__PURE__ */ jsx3("td", { children: e.rowNumber ?? "\u2014" }),
|
|
736
|
+
/* @__PURE__ */ jsx3("td", { children: e.errorType }),
|
|
737
|
+
/* @__PURE__ */ jsx3("td", { children: e.errorDetail })
|
|
738
|
+
] }, e.id ?? i)) })
|
|
739
|
+
] }) : /* @__PURE__ */ jsxs3("p", { className: "cfi-vi-muted", children: [
|
|
740
|
+
u.rowsFailed,
|
|
741
|
+
" error(s) \u2014 loading\u2026"
|
|
742
|
+
] })
|
|
743
|
+
] })
|
|
744
|
+
] }, `${u.id}-detail`)
|
|
745
|
+
] });
|
|
746
|
+
}) })
|
|
747
|
+
] }),
|
|
748
|
+
totalPages > 1 && /* @__PURE__ */ jsxs3("div", { className: "cfi-vi-row cfi-vi-files-pager", children: [
|
|
749
|
+
/* @__PURE__ */ jsx3(Btn, { variant: "outline", size: "sm", disabled: offset === 0, onClick: () => setOffset((o) => Math.max(0, o - PAGE_SIZE)), children: "\u2190 Prev" }),
|
|
750
|
+
/* @__PURE__ */ jsxs3("span", { className: "cfi-vi-muted", children: [
|
|
751
|
+
"Page ",
|
|
752
|
+
currentPage,
|
|
753
|
+
" of ",
|
|
754
|
+
totalPages
|
|
755
|
+
] }),
|
|
756
|
+
/* @__PURE__ */ jsx3(Btn, { variant: "outline", size: "sm", disabled: offset + PAGE_SIZE >= total, onClick: () => setOffset((o) => o + PAGE_SIZE), children: "Next \u2192" })
|
|
757
|
+
] }),
|
|
758
|
+
dialogOpen && /* @__PURE__ */ jsx3(
|
|
759
|
+
UploadDialog,
|
|
760
|
+
{
|
|
761
|
+
transport,
|
|
762
|
+
sources: dialogSources,
|
|
763
|
+
activeSourceId,
|
|
764
|
+
calendarSeeded,
|
|
765
|
+
onClose: () => setDialogOpen(false),
|
|
766
|
+
onCreated: handleCreated
|
|
767
|
+
}
|
|
768
|
+
)
|
|
769
|
+
] });
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// src/VolumeSourcesList.tsx
|
|
773
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useState as useState3 } from "react";
|
|
774
|
+
import { CheckCircle2, Sparkles } from "lucide-react";
|
|
775
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
776
|
+
var EMPTY_FORM = { code: "", name: "", description: "", headerRowIndex: 0, volumeHeaderFormat: "MMM yyyy" };
|
|
777
|
+
function VolumeSourcesList({ transport, onOpenSource, renderActiveSourceExtras, className }) {
|
|
778
|
+
const [sources, setSources] = useState3([]);
|
|
779
|
+
const [activeSourceId, setActiveSourceId] = useState3(null);
|
|
780
|
+
const [templates, setTemplates] = useState3([]);
|
|
781
|
+
const [loading, setLoading] = useState3(true);
|
|
782
|
+
const [error, setError] = useState3(null);
|
|
783
|
+
const [showCreate, setShowCreate] = useState3(false);
|
|
784
|
+
const [showTemplates, setShowTemplates] = useState3(false);
|
|
785
|
+
const [form, setForm] = useState3(EMPTY_FORM);
|
|
786
|
+
const [saving, setSaving] = useState3(false);
|
|
787
|
+
const [activating, setActivating] = useState3(null);
|
|
788
|
+
const [addingTemplate, setAddingTemplate] = useState3(null);
|
|
789
|
+
const [confirmActivate, setConfirmActivate] = useState3(null);
|
|
790
|
+
const load = useCallback3(async () => {
|
|
342
791
|
try {
|
|
343
792
|
setLoading(true);
|
|
344
793
|
const [allSources, config, allTemplates] = await Promise.all([
|
|
@@ -355,11 +804,11 @@ function VolumeSourcesList({ transport, onOpenSource, renderActiveSourceExtras,
|
|
|
355
804
|
setLoading(false);
|
|
356
805
|
}
|
|
357
806
|
}, [transport]);
|
|
358
|
-
|
|
807
|
+
useEffect3(() => {
|
|
359
808
|
void load();
|
|
360
809
|
}, [load]);
|
|
361
810
|
const availableTemplates = templates.filter((t) => !sources.some((s) => s.code === t.code));
|
|
362
|
-
const handleAddFromTemplate =
|
|
811
|
+
const handleAddFromTemplate = useCallback3(async (code) => {
|
|
363
812
|
setAddingTemplate(code);
|
|
364
813
|
setError(null);
|
|
365
814
|
try {
|
|
@@ -372,7 +821,7 @@ function VolumeSourcesList({ transport, onOpenSource, renderActiveSourceExtras,
|
|
|
372
821
|
setAddingTemplate(null);
|
|
373
822
|
}
|
|
374
823
|
}, [transport, onOpenSource]);
|
|
375
|
-
const handleCreate =
|
|
824
|
+
const handleCreate = useCallback3(async () => {
|
|
376
825
|
if (!form.code || !form.name) return;
|
|
377
826
|
setSaving(true);
|
|
378
827
|
try {
|
|
@@ -386,7 +835,7 @@ function VolumeSourcesList({ transport, onOpenSource, renderActiveSourceExtras,
|
|
|
386
835
|
setSaving(false);
|
|
387
836
|
}
|
|
388
837
|
}, [form, transport, load]);
|
|
389
|
-
const doActivate =
|
|
838
|
+
const doActivate = useCallback3(async (sourceId) => {
|
|
390
839
|
setActivating(sourceId);
|
|
391
840
|
setConfirmActivate(null);
|
|
392
841
|
try {
|
|
@@ -398,7 +847,7 @@ function VolumeSourcesList({ transport, onOpenSource, renderActiveSourceExtras,
|
|
|
398
847
|
setActivating(null);
|
|
399
848
|
}
|
|
400
849
|
}, [transport, load]);
|
|
401
|
-
const handleActivate =
|
|
850
|
+
const handleActivate = useCallback3((src) => {
|
|
402
851
|
if (activeSourceId && activeSourceId !== src.id) {
|
|
403
852
|
setConfirmActivate(src);
|
|
404
853
|
return;
|
|
@@ -406,127 +855,127 @@ function VolumeSourcesList({ transport, onOpenSource, renderActiveSourceExtras,
|
|
|
406
855
|
void doActivate(src.id);
|
|
407
856
|
}, [activeSourceId, doActivate]);
|
|
408
857
|
const currentActive = sources.find((s) => s.id === activeSourceId);
|
|
409
|
-
if (loading) return /* @__PURE__ */
|
|
410
|
-
return /* @__PURE__ */
|
|
411
|
-
/* @__PURE__ */
|
|
412
|
-
/* @__PURE__ */
|
|
413
|
-
/* @__PURE__ */
|
|
414
|
-
currentActive && /* @__PURE__ */
|
|
415
|
-
/* @__PURE__ */
|
|
858
|
+
if (loading) return /* @__PURE__ */ jsx4(Root, { className, children: /* @__PURE__ */ jsx4("p", { className: "cfi-vi-muted", children: "Loading\u2026" }) });
|
|
859
|
+
return /* @__PURE__ */ jsxs4(Root, { className, children: [
|
|
860
|
+
/* @__PURE__ */ jsxs4("div", { className: "cfi-vi-list-head", children: [
|
|
861
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
862
|
+
/* @__PURE__ */ jsx4("h1", { className: "cfi-vi-h1", children: "Volume Sources" }),
|
|
863
|
+
currentActive && /* @__PURE__ */ jsxs4("p", { className: "cfi-vi-active-line", children: [
|
|
864
|
+
/* @__PURE__ */ jsx4(CheckCircle2, { size: 14, color: "#16a34a", "aria-hidden": true }),
|
|
416
865
|
"Active: ",
|
|
417
|
-
/* @__PURE__ */
|
|
418
|
-
/* @__PURE__ */
|
|
866
|
+
/* @__PURE__ */ jsx4("span", { className: "cfi-vi-active-name", children: currentActive.name }),
|
|
867
|
+
/* @__PURE__ */ jsxs4("span", { className: "cfi-vi-muted", children: [
|
|
419
868
|
"(",
|
|
420
869
|
currentActive.code,
|
|
421
870
|
")"
|
|
422
871
|
] })
|
|
423
872
|
] })
|
|
424
873
|
] }),
|
|
425
|
-
/* @__PURE__ */
|
|
426
|
-
availableTemplates.length > 0 && /* @__PURE__ */
|
|
427
|
-
/* @__PURE__ */
|
|
874
|
+
/* @__PURE__ */ jsxs4("div", { className: "cfi-vi-row", children: [
|
|
875
|
+
availableTemplates.length > 0 && /* @__PURE__ */ jsxs4(Btn, { variant: "outline", size: "sm", onClick: () => setShowTemplates(true), children: [
|
|
876
|
+
/* @__PURE__ */ jsx4(Sparkles, { size: 14, "aria-hidden": true }),
|
|
428
877
|
" Add from template"
|
|
429
878
|
] }),
|
|
430
|
-
/* @__PURE__ */
|
|
879
|
+
/* @__PURE__ */ jsx4(Btn, { size: "sm", onClick: () => setShowCreate(true), children: "Add Source" })
|
|
431
880
|
] })
|
|
432
881
|
] }),
|
|
433
|
-
error && /* @__PURE__ */
|
|
434
|
-
/* @__PURE__ */
|
|
435
|
-
sources.length === 0 && /* @__PURE__ */
|
|
882
|
+
error && /* @__PURE__ */ jsx4("p", { className: "cfi-vi-error", children: error }),
|
|
883
|
+
/* @__PURE__ */ jsxs4("div", { className: "cfi-vi-list", children: [
|
|
884
|
+
sources.length === 0 && /* @__PURE__ */ jsx4("p", { className: "cfi-vi-muted", children: "No sources defined yet." }),
|
|
436
885
|
sources.map((src) => {
|
|
437
886
|
const isActive = src.id === activeSourceId;
|
|
438
|
-
return /* @__PURE__ */
|
|
439
|
-
/* @__PURE__ */
|
|
440
|
-
/* @__PURE__ */
|
|
441
|
-
/* @__PURE__ */
|
|
442
|
-
isActive && /* @__PURE__ */
|
|
443
|
-
src.kind === "overlay" && /* @__PURE__ */
|
|
887
|
+
return /* @__PURE__ */ jsxs4(Card, { className: isActive ? "cfi-vi-card--active" : "cfi-vi-card--hover", children: [
|
|
888
|
+
/* @__PURE__ */ jsx4(CardHeader, { children: /* @__PURE__ */ jsxs4("div", { className: "cfi-vi-row cfi-vi-row--between", children: [
|
|
889
|
+
/* @__PURE__ */ jsxs4("span", { className: "cfi-vi-card-title", children: [
|
|
890
|
+
/* @__PURE__ */ jsx4("button", { type: "button", className: "cfi-vi-link", onClick: () => onOpenSource(src.id), children: src.name }),
|
|
891
|
+
isActive && /* @__PURE__ */ jsx4(Badge, { variant: "success", children: "Active" }),
|
|
892
|
+
src.kind === "overlay" && /* @__PURE__ */ jsx4(Badge, { variant: "purple", title: "Overlay sources are active whenever data is uploaded \u2014 no Set Active step.", children: "Overlay" })
|
|
444
893
|
] }),
|
|
445
|
-
/* @__PURE__ */
|
|
446
|
-
/* @__PURE__ */
|
|
447
|
-
!src.isActive && /* @__PURE__ */
|
|
448
|
-
!isActive && src.kind === "base" && /* @__PURE__ */
|
|
894
|
+
/* @__PURE__ */ jsxs4("span", { className: "cfi-vi-row", children: [
|
|
895
|
+
/* @__PURE__ */ jsx4(Badge, { variant: "outline", children: src.code }),
|
|
896
|
+
!src.isActive && /* @__PURE__ */ jsx4(Badge, { variant: "secondary", children: "Disabled" }),
|
|
897
|
+
!isActive && src.kind === "base" && /* @__PURE__ */ jsx4(Btn, { variant: "outline", size: "sm", disabled: activating === src.id, onClick: () => handleActivate(src), children: activating === src.id ? "Activating\u2026" : "Set Active" })
|
|
449
898
|
] })
|
|
450
899
|
] }) }),
|
|
451
|
-
/* @__PURE__ */
|
|
452
|
-
/* @__PURE__ */
|
|
900
|
+
/* @__PURE__ */ jsxs4(CardBody, { children: [
|
|
901
|
+
/* @__PURE__ */ jsxs4("p", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-sm, 13px)" }, children: [
|
|
453
902
|
src.description || "No description",
|
|
454
903
|
" \xB7 ",
|
|
455
|
-
/* @__PURE__ */
|
|
904
|
+
/* @__PURE__ */ jsx4("span", { className: "cfi-vi-mono", children: src.volumeHeaderFormat })
|
|
456
905
|
] }),
|
|
457
|
-
src._count && /* @__PURE__ */
|
|
906
|
+
src._count && /* @__PURE__ */ jsxs4("p", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-xs, 11px)", marginTop: 4 }, children: [
|
|
458
907
|
src._count.segments,
|
|
459
908
|
" segments detected"
|
|
460
909
|
] }),
|
|
461
|
-
isActive && renderActiveSourceExtras && /* @__PURE__ */
|
|
910
|
+
isActive && renderActiveSourceExtras && /* @__PURE__ */ jsx4("div", { className: "cfi-vi-active-extras", children: renderActiveSourceExtras(src) })
|
|
462
911
|
] })
|
|
463
912
|
] }, src.id);
|
|
464
913
|
})
|
|
465
914
|
] }),
|
|
466
|
-
/* @__PURE__ */
|
|
915
|
+
/* @__PURE__ */ jsxs4(
|
|
467
916
|
Modal,
|
|
468
917
|
{
|
|
469
918
|
open: !!confirmActivate,
|
|
470
919
|
onClose: () => setConfirmActivate(null),
|
|
471
920
|
title: "Switch active source?",
|
|
472
|
-
footer: /* @__PURE__ */
|
|
473
|
-
/* @__PURE__ */
|
|
474
|
-
/* @__PURE__ */
|
|
921
|
+
footer: /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
922
|
+
/* @__PURE__ */ jsx4(Btn, { variant: "outline", onClick: () => setConfirmActivate(null), children: "Cancel" }),
|
|
923
|
+
/* @__PURE__ */ jsx4(Btn, { variant: "destructive", onClick: () => confirmActivate && void doActivate(confirmActivate.id), children: "Switch and wipe data" })
|
|
475
924
|
] }),
|
|
476
925
|
children: [
|
|
477
|
-
/* @__PURE__ */
|
|
926
|
+
/* @__PURE__ */ jsxs4("p", { children: [
|
|
478
927
|
"Switching the active source to ",
|
|
479
|
-
/* @__PURE__ */
|
|
928
|
+
/* @__PURE__ */ jsx4("strong", { children: confirmActivate?.name }),
|
|
480
929
|
" (",
|
|
481
930
|
confirmActivate?.code,
|
|
482
931
|
")."
|
|
483
932
|
] }),
|
|
484
|
-
/* @__PURE__ */
|
|
933
|
+
/* @__PURE__ */ jsx4("p", { className: "cfi-vi-error", children: "This permanently wipes all ingested data for this tenant \u2014 volume hierarchy, forecast data, edits, scenarios, uploads, and audit log. Your level 1\u20133 mapping and segment configuration are preserved. This cannot be undone." })
|
|
485
934
|
]
|
|
486
935
|
}
|
|
487
936
|
),
|
|
488
|
-
/* @__PURE__ */
|
|
937
|
+
/* @__PURE__ */ jsxs4(
|
|
489
938
|
Modal,
|
|
490
939
|
{
|
|
491
940
|
open: showCreate,
|
|
492
941
|
onClose: () => setShowCreate(false),
|
|
493
942
|
title: "Add volume source",
|
|
494
|
-
footer: /* @__PURE__ */
|
|
495
|
-
/* @__PURE__ */
|
|
496
|
-
/* @__PURE__ */
|
|
943
|
+
footer: /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
944
|
+
/* @__PURE__ */ jsx4(Btn, { variant: "outline", onClick: () => setShowCreate(false), children: "Cancel" }),
|
|
945
|
+
/* @__PURE__ */ jsx4(Btn, { onClick: handleCreate, disabled: saving || !form.code || !form.name, children: saving ? "Creating\u2026" : "Create" })
|
|
497
946
|
] }),
|
|
498
947
|
children: [
|
|
499
|
-
/* @__PURE__ */
|
|
500
|
-
/* @__PURE__ */
|
|
501
|
-
/* @__PURE__ */
|
|
502
|
-
/* @__PURE__ */
|
|
503
|
-
/* @__PURE__ */
|
|
948
|
+
/* @__PURE__ */ jsx4(Field, { label: "Code", children: /* @__PURE__ */ jsx4(TextInput, { placeholder: "e.g. IHS", value: form.code, onChange: (e) => setForm((f) => ({ ...f, code: e.target.value.toUpperCase() })) }) }),
|
|
949
|
+
/* @__PURE__ */ jsx4(Field, { label: "Name", children: /* @__PURE__ */ jsx4(TextInput, { placeholder: "e.g. IHS Market Production Forecast", value: form.name, onChange: (e) => setForm((f) => ({ ...f, name: e.target.value })) }) }),
|
|
950
|
+
/* @__PURE__ */ jsx4(Field, { label: "Description", children: /* @__PURE__ */ jsx4(TextInput, { value: form.description, onChange: (e) => setForm((f) => ({ ...f, description: e.target.value })) }) }),
|
|
951
|
+
/* @__PURE__ */ jsx4(Field, { label: "Volume header format", hint: 'e.g. "MMM yyyy" for "Jan 2025", or "MMM_yyyy VehicleVolume" for AFS', children: /* @__PURE__ */ jsx4(TextInput, { placeholder: "MMM yyyy", value: form.volumeHeaderFormat, onChange: (e) => setForm((f) => ({ ...f, volumeHeaderFormat: e.target.value })) }) }),
|
|
952
|
+
/* @__PURE__ */ jsx4(Field, { label: "Header row index (0-based)", children: /* @__PURE__ */ jsx4(TextInput, { type: "number", value: form.headerRowIndex, onChange: (e) => setForm((f) => ({ ...f, headerRowIndex: parseInt(e.target.value, 10) || 0 })) }) })
|
|
504
953
|
]
|
|
505
954
|
}
|
|
506
955
|
),
|
|
507
|
-
/* @__PURE__ */
|
|
956
|
+
/* @__PURE__ */ jsxs4(
|
|
508
957
|
Modal,
|
|
509
958
|
{
|
|
510
959
|
open: showTemplates,
|
|
511
960
|
onClose: () => setShowTemplates(false),
|
|
512
961
|
title: "Add source from template",
|
|
513
|
-
footer: /* @__PURE__ */
|
|
962
|
+
footer: /* @__PURE__ */ jsx4(Btn, { variant: "outline", onClick: () => setShowTemplates(false), children: "Close" }),
|
|
514
963
|
children: [
|
|
515
|
-
/* @__PURE__ */
|
|
516
|
-
availableTemplates.length === 0 ? /* @__PURE__ */
|
|
964
|
+
/* @__PURE__ */ jsx4("p", { className: "cfi-vi-muted", children: "Templates ship with their segments and default mappings wired up \u2014 pick one to skip manual setup. You can rename, edit columns, or change the layout on the source detail page afterward." }),
|
|
965
|
+
availableTemplates.length === 0 ? /* @__PURE__ */ jsxs4("p", { className: "cfi-vi-muted", children: [
|
|
517
966
|
"You already have every available template. Use ",
|
|
518
|
-
/* @__PURE__ */
|
|
967
|
+
/* @__PURE__ */ jsx4("strong", { children: "Add Source" }),
|
|
519
968
|
" to add another by hand."
|
|
520
|
-
] }) : availableTemplates.map((t) => /* @__PURE__ */
|
|
521
|
-
/* @__PURE__ */
|
|
522
|
-
/* @__PURE__ */
|
|
969
|
+
] }) : availableTemplates.map((t) => /* @__PURE__ */ jsxs4(Card, { className: "cfi-vi-card--hover", children: [
|
|
970
|
+
/* @__PURE__ */ jsx4(CardHeader, { children: /* @__PURE__ */ jsxs4("div", { className: "cfi-vi-row cfi-vi-row--between", children: [
|
|
971
|
+
/* @__PURE__ */ jsxs4("span", { className: "cfi-vi-card-title", children: [
|
|
523
972
|
t.name,
|
|
524
973
|
" ",
|
|
525
|
-
/* @__PURE__ */
|
|
974
|
+
/* @__PURE__ */ jsx4(Badge, { variant: "outline", children: t.code })
|
|
526
975
|
] }),
|
|
527
|
-
/* @__PURE__ */
|
|
976
|
+
/* @__PURE__ */ jsx4(Btn, { size: "sm", onClick: () => void handleAddFromTemplate(t.code), disabled: addingTemplate !== null, children: addingTemplate === t.code ? "Adding\u2026" : "Add" })
|
|
528
977
|
] }) }),
|
|
529
|
-
t.description && /* @__PURE__ */
|
|
978
|
+
t.description && /* @__PURE__ */ jsx4(CardBody, { children: /* @__PURE__ */ jsx4("p", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-xs, 11px)" }, children: t.description }) })
|
|
530
979
|
] }, t.code))
|
|
531
980
|
]
|
|
532
981
|
}
|
|
@@ -535,7 +984,7 @@ function VolumeSourcesList({ transport, onOpenSource, renderActiveSourceExtras,
|
|
|
535
984
|
}
|
|
536
985
|
|
|
537
986
|
// src/UnifiedSegmentMapper.tsx
|
|
538
|
-
import { useEffect as
|
|
987
|
+
import { useEffect as useEffect4, useMemo as useMemo3, useState as useState4 } from "react";
|
|
539
988
|
import { Search, CheckCircle2 as CheckCircle22 } from "lucide-react";
|
|
540
989
|
|
|
541
990
|
// src/constants.ts
|
|
@@ -566,7 +1015,7 @@ var AUTOMOTIVE_TRANSFORM_LABELS = {
|
|
|
566
1015
|
};
|
|
567
1016
|
|
|
568
1017
|
// src/UnifiedSegmentMapper.tsx
|
|
569
|
-
import { jsx as
|
|
1018
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
570
1019
|
var LEVELS = [1, 2, 3, 4, 5, 6];
|
|
571
1020
|
function UnifiedSegmentMapper({
|
|
572
1021
|
segments,
|
|
@@ -581,12 +1030,12 @@ function UnifiedSegmentMapper({
|
|
|
581
1030
|
baseHierarchyHint
|
|
582
1031
|
}) {
|
|
583
1032
|
const isSparse = hierarchyMode === "sparse";
|
|
584
|
-
const [hierAssign, setHierAssign] =
|
|
585
|
-
const [autoAssign, setAutoAssign] =
|
|
586
|
-
const [searchQuery, setSearchQuery] =
|
|
587
|
-
const [dragging, setDragging] =
|
|
588
|
-
const [dropTarget, setDropTarget] =
|
|
589
|
-
|
|
1033
|
+
const [hierAssign, setHierAssign] = useState4({});
|
|
1034
|
+
const [autoAssign, setAutoAssign] = useState4({});
|
|
1035
|
+
const [searchQuery, setSearchQuery] = useState4("");
|
|
1036
|
+
const [dragging, setDragging] = useState4(null);
|
|
1037
|
+
const [dropTarget, setDropTarget] = useState4(null);
|
|
1038
|
+
useEffect4(() => {
|
|
590
1039
|
const initHier = {};
|
|
591
1040
|
for (const lv of LEVELS) {
|
|
592
1041
|
initHier[lv] = hierarchyInitial.find((m) => m.targetKey === `level${lv}`)?.segmentId ?? null;
|
|
@@ -602,18 +1051,18 @@ function UnifiedSegmentMapper({
|
|
|
602
1051
|
}
|
|
603
1052
|
setAutoAssign(initAuto);
|
|
604
1053
|
}, [hierarchyInitial, automotiveInitial, automotiveSlots]);
|
|
605
|
-
const segmentById =
|
|
606
|
-
const usedIds =
|
|
1054
|
+
const segmentById = useMemo3(() => new Map(segments.map((s) => [s.id, s])), [segments]);
|
|
1055
|
+
const usedIds = useMemo3(() => {
|
|
607
1056
|
const s = /* @__PURE__ */ new Set();
|
|
608
1057
|
for (const v of Object.values(hierAssign)) if (v) s.add(v);
|
|
609
1058
|
for (const a of Object.values(autoAssign)) if (a.segmentId) s.add(a.segmentId);
|
|
610
1059
|
return s;
|
|
611
1060
|
}, [hierAssign, autoAssign]);
|
|
612
|
-
const poolSegments =
|
|
1061
|
+
const poolSegments = useMemo3(() => {
|
|
613
1062
|
const q = searchQuery.trim().toLowerCase();
|
|
614
1063
|
return segments.filter((s) => !usedIds.has(s.id)).filter((s) => !q || s.label.toLowerCase().includes(q)).sort((a, b) => a.label.localeCompare(b.label));
|
|
615
1064
|
}, [segments, usedIds, searchQuery]);
|
|
616
|
-
const hierarchyCoveredKeys =
|
|
1065
|
+
const hierarchyCoveredKeys = useMemo3(() => {
|
|
617
1066
|
const covered = /* @__PURE__ */ new Set();
|
|
618
1067
|
for (const slot of automotiveSlots) {
|
|
619
1068
|
if (slot.hierarchyCoveredByLevel == null) continue;
|
|
@@ -622,7 +1071,7 @@ function UnifiedSegmentMapper({
|
|
|
622
1071
|
}
|
|
623
1072
|
return covered;
|
|
624
1073
|
}, [automotiveSlots, hierAssign, autoAssign]);
|
|
625
|
-
const hierarchyErrors =
|
|
1074
|
+
const hierarchyErrors = useMemo3(() => {
|
|
626
1075
|
if (isSparse) return [];
|
|
627
1076
|
const errors = [];
|
|
628
1077
|
for (let n = 2; n <= 6; n++) {
|
|
@@ -632,7 +1081,7 @@ function UnifiedSegmentMapper({
|
|
|
632
1081
|
}
|
|
633
1082
|
return errors;
|
|
634
1083
|
}, [hierAssign, isSparse]);
|
|
635
|
-
const missingAutomotive =
|
|
1084
|
+
const missingAutomotive = useMemo3(() => {
|
|
636
1085
|
const out = [];
|
|
637
1086
|
for (const slot of automotiveSlots) {
|
|
638
1087
|
if (hierarchyCoveredKeys.has(slot.key)) continue;
|
|
@@ -641,7 +1090,7 @@ function UnifiedSegmentMapper({
|
|
|
641
1090
|
}
|
|
642
1091
|
return out;
|
|
643
1092
|
}, [automotiveSlots, hierarchyCoveredKeys, hierAssign, autoAssign]);
|
|
644
|
-
const isDirty =
|
|
1093
|
+
const isDirty = useMemo3(() => {
|
|
645
1094
|
for (const lv of LEVELS) {
|
|
646
1095
|
const cur = hierAssign[lv] ?? null;
|
|
647
1096
|
const saved = hierarchyInitial.find((m) => m.targetKey === `level${lv}`)?.segmentId ?? null;
|
|
@@ -740,14 +1189,14 @@ function UnifiedSegmentMapper({
|
|
|
740
1189
|
await onSave(hierEntries, autoEntries);
|
|
741
1190
|
}
|
|
742
1191
|
void transformRules;
|
|
743
|
-
return /* @__PURE__ */
|
|
744
|
-
/* @__PURE__ */
|
|
745
|
-
/* @__PURE__ */
|
|
746
|
-
/* @__PURE__ */
|
|
747
|
-
/* @__PURE__ */
|
|
748
|
-
/* @__PURE__ */
|
|
1192
|
+
return /* @__PURE__ */ jsxs5("div", { className: "cfi-vi cfi-vi-mapper", children: [
|
|
1193
|
+
/* @__PURE__ */ jsxs5("div", { className: "cfi-vi-mapper-col", children: [
|
|
1194
|
+
/* @__PURE__ */ jsxs5("section", { className: "cfi-vi-mapper-section", children: [
|
|
1195
|
+
/* @__PURE__ */ jsxs5("div", { className: "cfi-vi-mapper-section-head", children: [
|
|
1196
|
+
/* @__PURE__ */ jsx5("h3", { className: "cfi-vi-mapper-h3", children: "Hierarchy Tree" }),
|
|
1197
|
+
/* @__PURE__ */ jsx5("span", { className: "cfi-vi-mapper-note", children: isSparse ? "Drag chips onto whichever levels your file actually has. Empty levels are fine." : "Drag a chip onto a level. L(n) needs L(n\u22121) first." })
|
|
749
1198
|
] }),
|
|
750
|
-
/* @__PURE__ */
|
|
1199
|
+
/* @__PURE__ */ jsx5("div", { className: "cfi-vi-mapper-box", children: LEVELS.map((level) => /* @__PURE__ */ jsx5(
|
|
751
1200
|
HierarchyRow,
|
|
752
1201
|
{
|
|
753
1202
|
level,
|
|
@@ -765,21 +1214,21 @@ function UnifiedSegmentMapper({
|
|
|
765
1214
|
},
|
|
766
1215
|
level
|
|
767
1216
|
)) }),
|
|
768
|
-
hierarchyErrors.length > 0 && /* @__PURE__ */
|
|
1217
|
+
hierarchyErrors.length > 0 && /* @__PURE__ */ jsx5("div", { children: hierarchyErrors.map((err) => /* @__PURE__ */ jsxs5("p", { className: "cfi-vi-mapper-err", children: [
|
|
769
1218
|
"\u26A0 ",
|
|
770
1219
|
err
|
|
771
1220
|
] }, err)) })
|
|
772
1221
|
] }),
|
|
773
|
-
automotiveSlots.length > 0 && /* @__PURE__ */
|
|
774
|
-
/* @__PURE__ */
|
|
775
|
-
/* @__PURE__ */
|
|
776
|
-
/* @__PURE__ */
|
|
1222
|
+
automotiveSlots.length > 0 && /* @__PURE__ */ jsxs5("section", { className: "cfi-vi-mapper-section", children: [
|
|
1223
|
+
/* @__PURE__ */ jsxs5("div", { className: "cfi-vi-mapper-section-head", children: [
|
|
1224
|
+
/* @__PURE__ */ jsx5("h3", { className: "cfi-vi-mapper-h3", children: "Automotive Fields" }),
|
|
1225
|
+
/* @__PURE__ */ jsx5("span", { className: "cfi-vi-mapper-note", children: "Brand / Nameplate / Plant Name come from the hierarchy unless overridden." })
|
|
777
1226
|
] }),
|
|
778
|
-
/* @__PURE__ */
|
|
1227
|
+
/* @__PURE__ */ jsx5("div", { className: "cfi-vi-mapper-box", children: automotiveSlots.map((slot) => {
|
|
779
1228
|
const covered = hierarchyCoveredKeys.has(slot.key);
|
|
780
1229
|
const hierarchySegId = slot.hierarchyCoveredByLevel != null ? hierAssign[slot.hierarchyCoveredByLevel] : null;
|
|
781
1230
|
const assignment = autoAssign[slot.key];
|
|
782
|
-
return /* @__PURE__ */
|
|
1231
|
+
return /* @__PURE__ */ jsx5(
|
|
783
1232
|
AutomotiveRow,
|
|
784
1233
|
{
|
|
785
1234
|
slot,
|
|
@@ -801,32 +1250,32 @@ function UnifiedSegmentMapper({
|
|
|
801
1250
|
slot.key
|
|
802
1251
|
);
|
|
803
1252
|
}) }),
|
|
804
|
-
missingAutomotive.length > 0 && /* @__PURE__ */
|
|
1253
|
+
missingAutomotive.length > 0 && /* @__PURE__ */ jsxs5("p", { className: "cfi-vi-mapper-err", children: [
|
|
805
1254
|
"\u26A0 Required: ",
|
|
806
1255
|
missingAutomotive.join(", ")
|
|
807
1256
|
] })
|
|
808
1257
|
] }),
|
|
809
|
-
/* @__PURE__ */
|
|
810
|
-
/* @__PURE__ */
|
|
811
|
-
isDirty && hierarchyErrors.length === 0 && missingAutomotive.length === 0 && !saving && /* @__PURE__ */
|
|
812
|
-
!isDirty && /* @__PURE__ */
|
|
1258
|
+
/* @__PURE__ */ jsxs5("div", { className: "cfi-vi-mapper-save", children: [
|
|
1259
|
+
/* @__PURE__ */ jsx5(Btn, { size: "sm", onClick: handleSave, disabled: !canSave, children: saving ? "Saving\u2026" : "Save Mapping" }),
|
|
1260
|
+
isDirty && hierarchyErrors.length === 0 && missingAutomotive.length === 0 && !saving && /* @__PURE__ */ jsx5("span", { className: "cfi-vi-mapper-dirty", children: "Unsaved changes" }),
|
|
1261
|
+
!isDirty && /* @__PURE__ */ jsx5("span", { className: "cfi-vi-muted", children: "Up to date" })
|
|
813
1262
|
] })
|
|
814
1263
|
] }),
|
|
815
|
-
/* @__PURE__ */
|
|
816
|
-
/* @__PURE__ */
|
|
817
|
-
/* @__PURE__ */
|
|
818
|
-
/* @__PURE__ */
|
|
1264
|
+
/* @__PURE__ */ jsxs5("aside", { className: "cfi-vi-pool-col", children: [
|
|
1265
|
+
/* @__PURE__ */ jsxs5("div", { className: "cfi-vi-mapper-section-head", children: [
|
|
1266
|
+
/* @__PURE__ */ jsx5("h3", { className: "cfi-vi-mapper-h3", children: "Segment Pool" }),
|
|
1267
|
+
/* @__PURE__ */ jsxs5("span", { className: "cfi-vi-mapper-note", children: [
|
|
819
1268
|
poolSegments.length,
|
|
820
1269
|
" of ",
|
|
821
1270
|
segments.length,
|
|
822
1271
|
" unused"
|
|
823
1272
|
] })
|
|
824
1273
|
] }),
|
|
825
|
-
/* @__PURE__ */
|
|
826
|
-
/* @__PURE__ */
|
|
827
|
-
/* @__PURE__ */
|
|
1274
|
+
/* @__PURE__ */ jsxs5("div", { className: "cfi-vi-search", children: [
|
|
1275
|
+
/* @__PURE__ */ jsx5(Search, { size: 14, className: "cfi-vi-search-icon", "aria-hidden": true }),
|
|
1276
|
+
/* @__PURE__ */ jsx5(TextInput, { type: "search", placeholder: "Filter segments\u2026", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value) })
|
|
828
1277
|
] }),
|
|
829
|
-
/* @__PURE__ */
|
|
1278
|
+
/* @__PURE__ */ jsx5(
|
|
830
1279
|
"div",
|
|
831
1280
|
{
|
|
832
1281
|
className: `cfi-vi-pool ${dropTarget === "pool" ? "cfi-vi-pool--active" : ""}`,
|
|
@@ -841,10 +1290,10 @@ function UnifiedSegmentMapper({
|
|
|
841
1290
|
e.preventDefault();
|
|
842
1291
|
if (dragging) dropOnPool(dragging);
|
|
843
1292
|
},
|
|
844
|
-
children: segments.length === 0 ? /* @__PURE__ */
|
|
1293
|
+
children: segments.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "cfi-vi-pool-empty", children: "No segments detected. Run \u201CDetect segments\u201D from the source page first." }) : poolSegments.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "cfi-vi-pool-empty", children: searchQuery ? "No segments match the filter." : "All segments assigned \u2014 drop a chip here to return it." }) : /* @__PURE__ */ jsx5("div", { className: "cfi-vi-chips", children: poolSegments.map((seg) => /* @__PURE__ */ jsx5(SegmentChip, { label: seg.label, onDragStart: () => startDrag(`pool:${seg.id}`), onDragEnd: endDrag }, seg.id)) })
|
|
845
1294
|
}
|
|
846
1295
|
),
|
|
847
|
-
/* @__PURE__ */
|
|
1296
|
+
/* @__PURE__ */ jsx5("p", { className: "cfi-vi-mapper-note", children: "Drag chips onto a hierarchy level or an automotive field. Drop a chip back here to unassign." })
|
|
848
1297
|
] })
|
|
849
1298
|
] });
|
|
850
1299
|
}
|
|
@@ -866,12 +1315,12 @@ function HierarchyRow({
|
|
|
866
1315
|
const isLeaf = level === 6;
|
|
867
1316
|
const indent = sparse ? 0 : (level - 1) * 22;
|
|
868
1317
|
const levelName = DEFAULT_LEVEL_NAMES[level];
|
|
869
|
-
return /* @__PURE__ */
|
|
870
|
-
!sparse && level > 1 && /* @__PURE__ */
|
|
871
|
-
/* @__PURE__ */
|
|
872
|
-
/* @__PURE__ */
|
|
873
|
-
isLeaf && !sparse && /* @__PURE__ */
|
|
874
|
-
/* @__PURE__ */
|
|
1318
|
+
return /* @__PURE__ */ jsxs5("div", { className: "cfi-vi-hier-row", style: { paddingLeft: `${indent}px` }, children: [
|
|
1319
|
+
!sparse && level > 1 && /* @__PURE__ */ jsx5("div", { className: "cfi-vi-hier-elbow" }),
|
|
1320
|
+
/* @__PURE__ */ jsx5("div", { className: `cfi-vi-hier-dot ${seg ? "cfi-vi-hier-dot--filled" : ""}` }),
|
|
1321
|
+
/* @__PURE__ */ jsx5("span", { className: "cfi-vi-hier-name", children: levelName }),
|
|
1322
|
+
isLeaf && !sparse && /* @__PURE__ */ jsx5("span", { className: "cfi-vi-leaf", children: "Leaf" }),
|
|
1323
|
+
/* @__PURE__ */ jsx5(
|
|
875
1324
|
"div",
|
|
876
1325
|
{
|
|
877
1326
|
className: `cfi-vi-dropzone ${isDropTarget ? "cfi-vi-dropzone--active" : seg ? "cfi-vi-dropzone--filled" : "cfi-vi-dropzone--empty"}`,
|
|
@@ -886,10 +1335,10 @@ function HierarchyRow({
|
|
|
886
1335
|
e.preventDefault();
|
|
887
1336
|
onDrop();
|
|
888
1337
|
},
|
|
889
|
-
children: seg ? /* @__PURE__ */
|
|
1338
|
+
children: seg ? /* @__PURE__ */ jsx5(AssignedChip, { seg, onDragStart: () => onChipDragStart(seg.id), onDragEnd: onChipDragEnd, onRemove: onChipRemove }) : /* @__PURE__ */ jsx5("span", { className: "cfi-vi-dropzone-ph", children: isDropTarget ? "Drop here" : "Drop a segment\u2026" })
|
|
890
1339
|
}
|
|
891
1340
|
),
|
|
892
|
-
baseHint && /* @__PURE__ */
|
|
1341
|
+
baseHint && /* @__PURE__ */ jsxs5("span", { className: "cfi-vi-base-hint", title: `Base source uses "${baseHint}" on ${levelName}. Match here for the overlay to join.`, children: [
|
|
893
1342
|
"base: ",
|
|
894
1343
|
baseHint
|
|
895
1344
|
] })
|
|
@@ -913,20 +1362,20 @@ function AutomotiveRow({
|
|
|
913
1362
|
}) {
|
|
914
1363
|
const assignedSeg = assignment?.segmentId ? segmentById.get(assignment.segmentId) : void 0;
|
|
915
1364
|
const requiredBadge = (slot.required || hierarchyEmpty) && !covered && !assignedSeg;
|
|
916
|
-
return /* @__PURE__ */
|
|
917
|
-
/* @__PURE__ */
|
|
918
|
-
/* @__PURE__ */
|
|
919
|
-
/* @__PURE__ */
|
|
920
|
-
requiredBadge && /* @__PURE__ */
|
|
1365
|
+
return /* @__PURE__ */ jsxs5("div", { className: "cfi-vi-auto-row", children: [
|
|
1366
|
+
/* @__PURE__ */ jsxs5("div", { className: "cfi-vi-auto-label", children: [
|
|
1367
|
+
/* @__PURE__ */ jsxs5("div", { className: "cfi-vi-row", children: [
|
|
1368
|
+
/* @__PURE__ */ jsx5("span", { className: "cfi-vi-auto-label-text", children: slot.label }),
|
|
1369
|
+
requiredBadge && /* @__PURE__ */ jsx5(Badge, { variant: "outline", children: "required" })
|
|
921
1370
|
] }),
|
|
922
|
-
slot.hierarchyCoveredByLevel != null && /* @__PURE__ */
|
|
1371
|
+
slot.hierarchyCoveredByLevel != null && /* @__PURE__ */ jsxs5("p", { className: `cfi-vi-auto-cover ${covered ? "cfi-vi-auto-cover--on" : ""}`, children: [
|
|
923
1372
|
covered ? "\u2713 " : "",
|
|
924
1373
|
"From L",
|
|
925
1374
|
slot.hierarchyCoveredByLevel,
|
|
926
1375
|
" hierarchy"
|
|
927
1376
|
] })
|
|
928
1377
|
] }),
|
|
929
|
-
/* @__PURE__ */
|
|
1378
|
+
/* @__PURE__ */ jsx5(
|
|
930
1379
|
"div",
|
|
931
1380
|
{
|
|
932
1381
|
className: `cfi-vi-dropzone ${isDropTarget ? "cfi-vi-dropzone--active" : assignedSeg ? "cfi-vi-dropzone--filled" : covered ? "cfi-vi-dropzone--covered" : "cfi-vi-dropzone--empty"}`,
|
|
@@ -941,15 +1390,15 @@ function AutomotiveRow({
|
|
|
941
1390
|
e.preventDefault();
|
|
942
1391
|
onDrop();
|
|
943
1392
|
},
|
|
944
|
-
children: assignedSeg ? /* @__PURE__ */
|
|
945
|
-
/* @__PURE__ */
|
|
946
|
-
/* @__PURE__ */
|
|
947
|
-
/* @__PURE__ */
|
|
948
|
-
] }) : /* @__PURE__ */
|
|
1393
|
+
children: assignedSeg ? /* @__PURE__ */ jsx5(AssignedChip, { seg: assignedSeg, onDragStart: () => onChipDragStart(assignedSeg.id), onDragEnd: onChipDragEnd, onRemove: onChipRemove }) : covered && hierarchySegment ? /* @__PURE__ */ jsxs5("div", { className: "cfi-vi-auto-auto", title: "Auto-supplied from hierarchy. Drop a different chip here to override.", children: [
|
|
1394
|
+
/* @__PURE__ */ jsx5(CheckCircle22, { size: 14, "aria-hidden": true }),
|
|
1395
|
+
/* @__PURE__ */ jsx5("span", { className: "cfi-vi-auto-auto-label", children: hierarchySegment.label }),
|
|
1396
|
+
/* @__PURE__ */ jsx5("span", { className: "cfi-vi-auto-auto-tag", children: "auto" })
|
|
1397
|
+
] }) : /* @__PURE__ */ jsx5("span", { className: "cfi-vi-dropzone-ph", children: isDropTarget ? "Drop here" : "Drop a segment\u2026" })
|
|
949
1398
|
}
|
|
950
1399
|
),
|
|
951
|
-
slot.defaultTransform && !covered && /* @__PURE__ */
|
|
952
|
-
/* @__PURE__ */
|
|
1400
|
+
slot.defaultTransform && !covered && /* @__PURE__ */ jsxs5("div", { className: "cfi-vi-auto-transform", children: [
|
|
1401
|
+
/* @__PURE__ */ jsx5("span", { className: "cfi-vi-auto-transform-label", children: "Transform:" }),
|
|
953
1402
|
" ",
|
|
954
1403
|
transformRuleLabels[slot.defaultTransform] ?? slot.defaultTransform
|
|
955
1404
|
] })
|
|
@@ -961,38 +1410,38 @@ function AssignedChip({
|
|
|
961
1410
|
onDragEnd,
|
|
962
1411
|
onRemove
|
|
963
1412
|
}) {
|
|
964
|
-
return /* @__PURE__ */
|
|
965
|
-
/* @__PURE__ */
|
|
966
|
-
/* @__PURE__ */
|
|
967
|
-
/* @__PURE__ */
|
|
1413
|
+
return /* @__PURE__ */ jsxs5("div", { draggable: true, onDragStart, onDragEnd, className: "cfi-vi-chip--assigned", children: [
|
|
1414
|
+
/* @__PURE__ */ jsx5("div", { className: "cfi-vi-chip-dot cfi-vi-chip-dot--on" }),
|
|
1415
|
+
/* @__PURE__ */ jsx5("span", { className: "cfi-vi-chip-label", children: seg.label }),
|
|
1416
|
+
/* @__PURE__ */ jsx5("button", { type: "button", onClick: (e) => {
|
|
968
1417
|
e.stopPropagation();
|
|
969
1418
|
onRemove();
|
|
970
1419
|
}, className: "cfi-vi-chip-x", title: "Remove \u2014 returns to pool", children: "\xD7" })
|
|
971
1420
|
] });
|
|
972
1421
|
}
|
|
973
1422
|
function SegmentChip({ label, onDragStart, onDragEnd }) {
|
|
974
|
-
return /* @__PURE__ */
|
|
975
|
-
/* @__PURE__ */
|
|
1423
|
+
return /* @__PURE__ */ jsxs5("div", { draggable: true, onDragStart, onDragEnd, className: "cfi-vi-chip", children: [
|
|
1424
|
+
/* @__PURE__ */ jsx5("div", { className: "cfi-vi-chip-dot" }),
|
|
976
1425
|
label
|
|
977
1426
|
] });
|
|
978
1427
|
}
|
|
979
1428
|
|
|
980
1429
|
// src/VolumeSourceDetail.tsx
|
|
981
|
-
import { useEffect as
|
|
982
|
-
import { KeyRound, Lock, Rows, Columns, AlertTriangle as
|
|
1430
|
+
import { useEffect as useEffect7, useRef as useRef3, useState as useState7 } from "react";
|
|
1431
|
+
import { KeyRound, Lock, Rows, Columns, AlertTriangle as AlertTriangle3, Layers } from "lucide-react";
|
|
983
1432
|
|
|
984
1433
|
// src/TallLayoutMappings.tsx
|
|
985
|
-
import { useEffect as
|
|
986
|
-
import { jsx as
|
|
1434
|
+
import { useEffect as useEffect5, useMemo as useMemo4, useState as useState5 } from "react";
|
|
1435
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
987
1436
|
var NONE = "__none__";
|
|
988
1437
|
function TallLayoutMappings({ transport, source, locked }) {
|
|
989
|
-
const [loading, setLoading] =
|
|
990
|
-
const [saving, setSaving] =
|
|
991
|
-
const [error, setError] =
|
|
992
|
-
const [periodConfigured, setPeriodConfigured] =
|
|
993
|
-
const [valueConfigured, setValueConfigured] =
|
|
994
|
-
const [periodSegmentId, setPeriodSegmentId] =
|
|
995
|
-
const [valueSegmentId, setValueSegmentId] =
|
|
1438
|
+
const [loading, setLoading] = useState5(true);
|
|
1439
|
+
const [saving, setSaving] = useState5(null);
|
|
1440
|
+
const [error, setError] = useState5(null);
|
|
1441
|
+
const [periodConfigured, setPeriodConfigured] = useState5(false);
|
|
1442
|
+
const [valueConfigured, setValueConfigured] = useState5(false);
|
|
1443
|
+
const [periodSegmentId, setPeriodSegmentId] = useState5(NONE);
|
|
1444
|
+
const [valueSegmentId, setValueSegmentId] = useState5(NONE);
|
|
996
1445
|
async function load() {
|
|
997
1446
|
try {
|
|
998
1447
|
setLoading(true);
|
|
@@ -1010,10 +1459,10 @@ function TallLayoutMappings({ transport, source, locked }) {
|
|
|
1010
1459
|
setLoading(false);
|
|
1011
1460
|
}
|
|
1012
1461
|
}
|
|
1013
|
-
|
|
1462
|
+
useEffect5(() => {
|
|
1014
1463
|
void load();
|
|
1015
1464
|
}, [source.id]);
|
|
1016
|
-
const sortedSegments =
|
|
1465
|
+
const sortedSegments = useMemo4(
|
|
1017
1466
|
() => source.segments.slice().sort((a, b) => a.label.localeCompare(b.label)),
|
|
1018
1467
|
[source.segments]
|
|
1019
1468
|
);
|
|
@@ -1031,19 +1480,19 @@ function TallLayoutMappings({ transport, source, locked }) {
|
|
|
1031
1480
|
setSaving(null);
|
|
1032
1481
|
}
|
|
1033
1482
|
}
|
|
1034
|
-
if (loading) return /* @__PURE__ */
|
|
1483
|
+
if (loading) return /* @__PURE__ */ jsx6("p", { className: "cfi-vi-muted", children: "Loading tall-layout mappings\u2026" });
|
|
1035
1484
|
const ready = periodConfigured && valueConfigured;
|
|
1036
|
-
return /* @__PURE__ */
|
|
1037
|
-
/* @__PURE__ */
|
|
1038
|
-
/* @__PURE__ */
|
|
1039
|
-
/* @__PURE__ */
|
|
1485
|
+
return /* @__PURE__ */ jsxs6("section", { className: "cfi-vi-panel", children: [
|
|
1486
|
+
/* @__PURE__ */ jsxs6("div", { className: "cfi-vi-row cfi-vi-row--between", children: [
|
|
1487
|
+
/* @__PURE__ */ jsx6("h2", { className: "cfi-vi-h2", children: "Tall-Layout Mappings" }),
|
|
1488
|
+
/* @__PURE__ */ jsx6("span", { style: { fontSize: "var(--cfi-font-size-xs, 12px)", color: ready ? "#16a34a" : "#b45309" }, children: ready ? "Ready for upload" : "Missing period or value mapping" })
|
|
1040
1489
|
] }),
|
|
1041
|
-
/* @__PURE__ */
|
|
1042
|
-
error && /* @__PURE__ */
|
|
1043
|
-
/* @__PURE__ */
|
|
1044
|
-
/* @__PURE__ */
|
|
1045
|
-
/* @__PURE__ */
|
|
1046
|
-
/* @__PURE__ */
|
|
1490
|
+
/* @__PURE__ */ jsx6("p", { className: "cfi-vi-muted", children: "Tall sources need to know which file column carries the period date and the volume value." }),
|
|
1491
|
+
error && /* @__PURE__ */ jsx6("p", { className: "cfi-vi-error", children: error }),
|
|
1492
|
+
/* @__PURE__ */ jsxs6("div", { className: "cfi-vi-field", children: [
|
|
1493
|
+
/* @__PURE__ */ jsx6("label", { className: "cfi-vi-label", children: "Period column (Week Ending)" }),
|
|
1494
|
+
/* @__PURE__ */ jsxs6("div", { className: "cfi-vi-row", children: [
|
|
1495
|
+
/* @__PURE__ */ jsxs6(
|
|
1047
1496
|
"select",
|
|
1048
1497
|
{
|
|
1049
1498
|
className: "cfi-vi-input",
|
|
@@ -1051,18 +1500,18 @@ function TallLayoutMappings({ transport, source, locked }) {
|
|
|
1051
1500
|
disabled: locked || saving !== null,
|
|
1052
1501
|
onChange: (e) => setPeriodSegmentId(e.target.value),
|
|
1053
1502
|
children: [
|
|
1054
|
-
/* @__PURE__ */
|
|
1055
|
-
sortedSegments.map((s) => /* @__PURE__ */
|
|
1503
|
+
/* @__PURE__ */ jsx6("option", { value: NONE, children: "\u2014 Not mapped \u2014" }),
|
|
1504
|
+
sortedSegments.map((s) => /* @__PURE__ */ jsx6("option", { value: s.id, children: s.label }, s.id))
|
|
1056
1505
|
]
|
|
1057
1506
|
}
|
|
1058
1507
|
),
|
|
1059
|
-
/* @__PURE__ */
|
|
1508
|
+
/* @__PURE__ */ jsx6(Btn, { size: "sm", onClick: () => void saveCategory("period", periodSegmentId, "week_date"), disabled: locked || saving !== null, children: saving === "period" ? "Saving\u2026" : "Save" })
|
|
1060
1509
|
] })
|
|
1061
1510
|
] }),
|
|
1062
|
-
/* @__PURE__ */
|
|
1063
|
-
/* @__PURE__ */
|
|
1064
|
-
/* @__PURE__ */
|
|
1065
|
-
/* @__PURE__ */
|
|
1511
|
+
/* @__PURE__ */ jsxs6("div", { className: "cfi-vi-field", children: [
|
|
1512
|
+
/* @__PURE__ */ jsx6("label", { className: "cfi-vi-label", children: "Quantity column (Volume)" }),
|
|
1513
|
+
/* @__PURE__ */ jsxs6("div", { className: "cfi-vi-row", children: [
|
|
1514
|
+
/* @__PURE__ */ jsxs6(
|
|
1066
1515
|
"select",
|
|
1067
1516
|
{
|
|
1068
1517
|
className: "cfi-vi-input",
|
|
@@ -1070,31 +1519,31 @@ function TallLayoutMappings({ transport, source, locked }) {
|
|
|
1070
1519
|
disabled: locked || saving !== null,
|
|
1071
1520
|
onChange: (e) => setValueSegmentId(e.target.value),
|
|
1072
1521
|
children: [
|
|
1073
|
-
/* @__PURE__ */
|
|
1074
|
-
sortedSegments.map((s) => /* @__PURE__ */
|
|
1522
|
+
/* @__PURE__ */ jsx6("option", { value: NONE, children: "\u2014 Not mapped \u2014" }),
|
|
1523
|
+
sortedSegments.map((s) => /* @__PURE__ */ jsx6("option", { value: s.id, children: s.label }, s.id))
|
|
1075
1524
|
]
|
|
1076
1525
|
}
|
|
1077
1526
|
),
|
|
1078
|
-
/* @__PURE__ */
|
|
1527
|
+
/* @__PURE__ */ jsx6(Btn, { size: "sm", onClick: () => void saveCategory("value", valueSegmentId, "quantity"), disabled: locked || saving !== null, children: saving === "value" ? "Saving\u2026" : "Save" })
|
|
1079
1528
|
] })
|
|
1080
1529
|
] })
|
|
1081
1530
|
] });
|
|
1082
1531
|
}
|
|
1083
1532
|
|
|
1084
1533
|
// src/ValueAliasesCard.tsx
|
|
1085
|
-
import { useEffect as
|
|
1534
|
+
import { useEffect as useEffect6, useMemo as useMemo5, useState as useState6 } from "react";
|
|
1086
1535
|
import { Plus, Trash2, ArrowRight, Save, RotateCw } from "lucide-react";
|
|
1087
|
-
import { jsx as
|
|
1536
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1088
1537
|
function ValueAliasesCard({ transport, sourceId, locked, isOverlay }) {
|
|
1089
|
-
const [selectedLevel, setSelectedLevel] =
|
|
1090
|
-
const [aliases, setAliases] =
|
|
1091
|
-
const [draft, setDraft] =
|
|
1092
|
-
const [saving, setSaving] =
|
|
1093
|
-
const [error, setError] =
|
|
1094
|
-
const [loading, setLoading] =
|
|
1095
|
-
const [relinking, setRelinking] =
|
|
1096
|
-
const [relinkResult, setRelinkResult] =
|
|
1097
|
-
|
|
1538
|
+
const [selectedLevel, setSelectedLevel] = useState6(4);
|
|
1539
|
+
const [aliases, setAliases] = useState6([]);
|
|
1540
|
+
const [draft, setDraft] = useState6([]);
|
|
1541
|
+
const [saving, setSaving] = useState6(false);
|
|
1542
|
+
const [error, setError] = useState6(null);
|
|
1543
|
+
const [loading, setLoading] = useState6(true);
|
|
1544
|
+
const [relinking, setRelinking] = useState6(false);
|
|
1545
|
+
const [relinkResult, setRelinkResult] = useState6(null);
|
|
1546
|
+
useEffect6(() => {
|
|
1098
1547
|
let cancelled = false;
|
|
1099
1548
|
setLoading(true);
|
|
1100
1549
|
void transport.listValueAliases(sourceId).then((items) => {
|
|
@@ -1111,12 +1560,12 @@ function ValueAliasesCard({ transport, sourceId, locked, isOverlay }) {
|
|
|
1111
1560
|
cancelled = true;
|
|
1112
1561
|
};
|
|
1113
1562
|
}, [sourceId, transport]);
|
|
1114
|
-
|
|
1563
|
+
useEffect6(() => {
|
|
1115
1564
|
setDraft(
|
|
1116
1565
|
aliases.filter((a) => a.level === selectedLevel).map((a) => ({ id: a.id, rawValue: a.rawValue, canonicalValue: a.canonicalValue }))
|
|
1117
1566
|
);
|
|
1118
1567
|
}, [aliases, selectedLevel]);
|
|
1119
|
-
const isDirty =
|
|
1568
|
+
const isDirty = useMemo5(() => {
|
|
1120
1569
|
const saved = aliases.filter((a) => a.level === selectedLevel).map((a) => `${a.rawValue}${a.canonicalValue}`).sort();
|
|
1121
1570
|
const current = draft.filter((d) => d.rawValue.trim() && d.canonicalValue.trim()).map((d) => `${d.rawValue.trim().toUpperCase()}${d.canonicalValue.trim().toUpperCase()}`).sort();
|
|
1122
1571
|
if (saved.length !== current.length) return true;
|
|
@@ -1152,20 +1601,20 @@ function ValueAliasesCard({ transport, sourceId, locked, isOverlay }) {
|
|
|
1152
1601
|
setSaving(false);
|
|
1153
1602
|
}
|
|
1154
1603
|
}
|
|
1155
|
-
if (loading) return /* @__PURE__ */
|
|
1156
|
-
return /* @__PURE__ */
|
|
1157
|
-
/* @__PURE__ */
|
|
1158
|
-
/* @__PURE__ */
|
|
1159
|
-
/* @__PURE__ */
|
|
1160
|
-
/* @__PURE__ */
|
|
1604
|
+
if (loading) return /* @__PURE__ */ jsx7("p", { className: "cfi-vi-muted", children: "Loading aliases\u2026" });
|
|
1605
|
+
return /* @__PURE__ */ jsxs7("div", { className: "cfi-vi-aliases", children: [
|
|
1606
|
+
/* @__PURE__ */ jsxs7("div", { className: "cfi-vi-row cfi-vi-row--between", children: [
|
|
1607
|
+
/* @__PURE__ */ jsxs7("div", { children: [
|
|
1608
|
+
/* @__PURE__ */ jsx7("h2", { className: "cfi-vi-h2", children: "Value Aliases" }),
|
|
1609
|
+
/* @__PURE__ */ jsxs7("p", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-xs, 11px)" }, children: [
|
|
1161
1610
|
"Normalise level values when this source uses different vocabulary than the base/overlay it joins to (e.g. ",
|
|
1162
|
-
/* @__PURE__ */
|
|
1611
|
+
/* @__PURE__ */ jsx7("span", { className: "cfi-vi-mono", children: '"MICHIGAN" \u2192 "MICHIGAN ASSEMBLY"' }),
|
|
1163
1612
|
"). Applied at match time \u2014 no re-upload."
|
|
1164
1613
|
] })
|
|
1165
1614
|
] }),
|
|
1166
|
-
/* @__PURE__ */
|
|
1167
|
-
/* @__PURE__ */
|
|
1168
|
-
/* @__PURE__ */
|
|
1615
|
+
/* @__PURE__ */ jsxs7("div", { className: "cfi-vi-field", style: { minWidth: 140 }, children: [
|
|
1616
|
+
/* @__PURE__ */ jsx7("label", { className: "cfi-vi-label", children: "Level" }),
|
|
1617
|
+
/* @__PURE__ */ jsx7("select", { className: "cfi-vi-input", value: String(selectedLevel), onChange: (e) => setSelectedLevel(parseInt(e.target.value, 10)), children: [1, 2, 3, 4, 5, 6].map((n) => /* @__PURE__ */ jsxs7("option", { value: n, children: [
|
|
1169
1618
|
"L",
|
|
1170
1619
|
n,
|
|
1171
1620
|
" \u2014 ",
|
|
@@ -1173,17 +1622,17 @@ function ValueAliasesCard({ transport, sourceId, locked, isOverlay }) {
|
|
|
1173
1622
|
] }, n)) })
|
|
1174
1623
|
] })
|
|
1175
1624
|
] }),
|
|
1176
|
-
/* @__PURE__ */
|
|
1177
|
-
draft.length === 0 ? /* @__PURE__ */
|
|
1625
|
+
/* @__PURE__ */ jsxs7("div", { className: "cfi-vi-panel", children: [
|
|
1626
|
+
draft.length === 0 ? /* @__PURE__ */ jsxs7("p", { className: "cfi-vi-muted", style: { fontStyle: "italic", fontSize: "var(--cfi-font-size-xs, 12px)" }, children: [
|
|
1178
1627
|
"No aliases at L",
|
|
1179
1628
|
selectedLevel,
|
|
1180
1629
|
" (",
|
|
1181
1630
|
DEFAULT_LEVEL_NAMES[selectedLevel],
|
|
1182
1631
|
"). Click ",
|
|
1183
|
-
/* @__PURE__ */
|
|
1632
|
+
/* @__PURE__ */ jsx7("strong", { children: "+ Add alias" }),
|
|
1184
1633
|
" to create one."
|
|
1185
|
-
] }) : /* @__PURE__ */
|
|
1186
|
-
/* @__PURE__ */
|
|
1634
|
+
] }) : /* @__PURE__ */ jsx7("div", { className: "cfi-vi-alias-rows", children: draft.map((row, i) => /* @__PURE__ */ jsxs7("div", { className: "cfi-vi-row", children: [
|
|
1635
|
+
/* @__PURE__ */ jsx7(
|
|
1187
1636
|
"input",
|
|
1188
1637
|
{
|
|
1189
1638
|
className: "cfi-vi-input cfi-vi-mono",
|
|
@@ -1194,8 +1643,8 @@ function ValueAliasesCard({ transport, sourceId, locked, isOverlay }) {
|
|
|
1194
1643
|
onChange: (e) => updateRow(i, { rawValue: e.target.value })
|
|
1195
1644
|
}
|
|
1196
1645
|
),
|
|
1197
|
-
/* @__PURE__ */
|
|
1198
|
-
/* @__PURE__ */
|
|
1646
|
+
/* @__PURE__ */ jsx7(ArrowRight, { size: 14, className: "cfi-vi-muted", "aria-hidden": true }),
|
|
1647
|
+
/* @__PURE__ */ jsx7(
|
|
1199
1648
|
"input",
|
|
1200
1649
|
{
|
|
1201
1650
|
className: "cfi-vi-input cfi-vi-mono",
|
|
@@ -1206,21 +1655,21 @@ function ValueAliasesCard({ transport, sourceId, locked, isOverlay }) {
|
|
|
1206
1655
|
onChange: (e) => updateRow(i, { canonicalValue: e.target.value })
|
|
1207
1656
|
}
|
|
1208
1657
|
),
|
|
1209
|
-
/* @__PURE__ */
|
|
1658
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: "cfi-vi-icon-btn", onClick: () => removeRow(i), disabled: locked, title: "Remove row", children: /* @__PURE__ */ jsx7(Trash2, { size: 14, "aria-hidden": true }) })
|
|
1210
1659
|
] }, i)) }),
|
|
1211
|
-
/* @__PURE__ */
|
|
1212
|
-
/* @__PURE__ */
|
|
1213
|
-
/* @__PURE__ */
|
|
1660
|
+
/* @__PURE__ */ jsxs7("div", { className: "cfi-vi-row", style: { flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
1661
|
+
/* @__PURE__ */ jsxs7(Btn, { variant: "outline", size: "sm", onClick: addRow, disabled: locked, children: [
|
|
1662
|
+
/* @__PURE__ */ jsx7(Plus, { size: 14, "aria-hidden": true }),
|
|
1214
1663
|
" Add alias"
|
|
1215
1664
|
] }),
|
|
1216
|
-
/* @__PURE__ */
|
|
1217
|
-
/* @__PURE__ */
|
|
1665
|
+
/* @__PURE__ */ jsxs7(Btn, { size: "sm", onClick: () => void handleSave(), disabled: !isDirty || saving || locked, children: [
|
|
1666
|
+
/* @__PURE__ */ jsx7(Save, { size: 14, "aria-hidden": true }),
|
|
1218
1667
|
" ",
|
|
1219
1668
|
saving ? "Saving\u2026" : "Save"
|
|
1220
1669
|
] }),
|
|
1221
|
-
isDirty && !saving && /* @__PURE__ */
|
|
1222
|
-
!isDirty && !saving && draft.length > 0 && /* @__PURE__ */
|
|
1223
|
-
isOverlay && /* @__PURE__ */
|
|
1670
|
+
isDirty && !saving && /* @__PURE__ */ jsx7("span", { className: "cfi-vi-mapper-dirty", children: "Unsaved changes" }),
|
|
1671
|
+
!isDirty && !saving && draft.length > 0 && /* @__PURE__ */ jsx7("span", { className: "cfi-vi-muted", children: "Up to date" }),
|
|
1672
|
+
isOverlay && /* @__PURE__ */ jsxs7(
|
|
1224
1673
|
Btn,
|
|
1225
1674
|
{
|
|
1226
1675
|
variant: "outline",
|
|
@@ -1229,46 +1678,46 @@ function ValueAliasesCard({ transport, sourceId, locked, isOverlay }) {
|
|
|
1229
1678
|
disabled: relinking || isDirty,
|
|
1230
1679
|
title: isDirty ? "Save aliases first, then re-link" : "Re-run overlay \u2192 base resolution against current aliases",
|
|
1231
1680
|
children: [
|
|
1232
|
-
/* @__PURE__ */
|
|
1681
|
+
/* @__PURE__ */ jsx7(RotateCw, { size: 14, className: relinking ? "cfi-vi-spin" : "", "aria-hidden": true }),
|
|
1233
1682
|
" ",
|
|
1234
1683
|
relinking ? "Re-linking\u2026" : "Re-link overlay"
|
|
1235
1684
|
]
|
|
1236
1685
|
}
|
|
1237
1686
|
)
|
|
1238
1687
|
] }),
|
|
1239
|
-
error && /* @__PURE__ */
|
|
1240
|
-
relinkResult && /* @__PURE__ */
|
|
1688
|
+
error && /* @__PURE__ */ jsx7("p", { className: "cfi-vi-error", children: error }),
|
|
1689
|
+
relinkResult && /* @__PURE__ */ jsx7("p", { style: { fontSize: "var(--cfi-font-size-xs, 12px)", color: "#15803d" }, children: relinkResult })
|
|
1241
1690
|
] })
|
|
1242
1691
|
] });
|
|
1243
1692
|
}
|
|
1244
1693
|
|
|
1245
1694
|
// src/VolumeSourceDetail.tsx
|
|
1246
|
-
import { Fragment as
|
|
1695
|
+
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1247
1696
|
function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, className }) {
|
|
1248
1697
|
const id = sourceId;
|
|
1249
|
-
const [source, setSource] =
|
|
1250
|
-
const [allSources, setAllSources] =
|
|
1251
|
-
const [loading, setLoading] =
|
|
1252
|
-
const [error, setError] =
|
|
1253
|
-
const [detecting, setDetecting] =
|
|
1254
|
-
const [detectMsg, setDetectMsg] =
|
|
1255
|
-
const [savingKey, setSavingKey] =
|
|
1256
|
-
const [selectedKeyId, setSelectedKeyId] =
|
|
1257
|
-
const [hasData, setHasData] =
|
|
1258
|
-
const fileRef =
|
|
1259
|
-
const [savingLayout, setSavingLayout] =
|
|
1260
|
-
const [editLayout, setEditLayout] =
|
|
1261
|
-
const [editValueDateFormat, setEditValueDateFormat] =
|
|
1262
|
-
const [newSegmentLabel, setNewSegmentLabel] =
|
|
1263
|
-
const [newSegmentDataType, setNewSegmentDataType] =
|
|
1264
|
-
const [addingSegment, setAddingSegment] =
|
|
1265
|
-
const [clearConfirm, setClearConfirm] =
|
|
1266
|
-
const [clearing, setClearing] =
|
|
1267
|
-
const [clearResult, setClearResult] =
|
|
1268
|
-
const [mappingKeys, setMappingKeys] =
|
|
1269
|
-
const [mappingRows, setMappingRows] =
|
|
1270
|
-
const [savingMapping, setSavingMapping] =
|
|
1271
|
-
const [baseHierarchyHint, setBaseHierarchyHint] =
|
|
1698
|
+
const [source, setSource] = useState7(null);
|
|
1699
|
+
const [allSources, setAllSources] = useState7([]);
|
|
1700
|
+
const [loading, setLoading] = useState7(true);
|
|
1701
|
+
const [error, setError] = useState7(null);
|
|
1702
|
+
const [detecting, setDetecting] = useState7(false);
|
|
1703
|
+
const [detectMsg, setDetectMsg] = useState7(null);
|
|
1704
|
+
const [savingKey, setSavingKey] = useState7(false);
|
|
1705
|
+
const [selectedKeyId, setSelectedKeyId] = useState7("__none__");
|
|
1706
|
+
const [hasData, setHasData] = useState7(false);
|
|
1707
|
+
const fileRef = useRef3(null);
|
|
1708
|
+
const [savingLayout, setSavingLayout] = useState7(false);
|
|
1709
|
+
const [editLayout, setEditLayout] = useState7("wide");
|
|
1710
|
+
const [editValueDateFormat, setEditValueDateFormat] = useState7("yyyy-MM-dd");
|
|
1711
|
+
const [newSegmentLabel, setNewSegmentLabel] = useState7("");
|
|
1712
|
+
const [newSegmentDataType, setNewSegmentDataType] = useState7("string");
|
|
1713
|
+
const [addingSegment, setAddingSegment] = useState7(false);
|
|
1714
|
+
const [clearConfirm, setClearConfirm] = useState7("");
|
|
1715
|
+
const [clearing, setClearing] = useState7(false);
|
|
1716
|
+
const [clearResult, setClearResult] = useState7(null);
|
|
1717
|
+
const [mappingKeys, setMappingKeys] = useState7(null);
|
|
1718
|
+
const [mappingRows, setMappingRows] = useState7([]);
|
|
1719
|
+
const [savingMapping, setSavingMapping] = useState7(false);
|
|
1720
|
+
const [baseHierarchyHint, setBaseHierarchyHint] = useState7({});
|
|
1272
1721
|
async function load() {
|
|
1273
1722
|
if (!id) return;
|
|
1274
1723
|
try {
|
|
@@ -1321,7 +1770,7 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1321
1770
|
setLoading(false);
|
|
1322
1771
|
}
|
|
1323
1772
|
}
|
|
1324
|
-
|
|
1773
|
+
useEffect7(() => {
|
|
1325
1774
|
void load();
|
|
1326
1775
|
}, [id]);
|
|
1327
1776
|
async function handleDetect(file) {
|
|
@@ -1420,15 +1869,15 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1420
1869
|
setSavingLayout(false);
|
|
1421
1870
|
}
|
|
1422
1871
|
}
|
|
1423
|
-
if (loading) return /* @__PURE__ */
|
|
1424
|
-
if (!source) return /* @__PURE__ */
|
|
1872
|
+
if (loading) return /* @__PURE__ */ jsx8(Root, { className, children: /* @__PURE__ */ jsx8("p", { className: "cfi-vi-muted", children: "Loading\u2026" }) });
|
|
1873
|
+
if (!source) return /* @__PURE__ */ jsx8(Root, { className, children: /* @__PURE__ */ jsx8("p", { className: "cfi-vi-error", children: "Source not found" }) });
|
|
1425
1874
|
const keySegment = source.segments.find((s) => s.id === source.uniqueKeySegmentId);
|
|
1426
1875
|
const isOverlay = source.kind === "overlay";
|
|
1427
|
-
return /* @__PURE__ */
|
|
1428
|
-
/* @__PURE__ */
|
|
1429
|
-
/* @__PURE__ */
|
|
1430
|
-
/* @__PURE__ */
|
|
1431
|
-
/* @__PURE__ */
|
|
1876
|
+
return /* @__PURE__ */ jsx8(Root, { className, children: /* @__PURE__ */ jsxs8("div", { className: "cfi-vi-detail", children: [
|
|
1877
|
+
/* @__PURE__ */ jsxs8("div", { children: [
|
|
1878
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", style: { gap: 8 }, children: [
|
|
1879
|
+
/* @__PURE__ */ jsx8("span", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-xs, 12px)" }, children: "Source:" }),
|
|
1880
|
+
/* @__PURE__ */ jsx8(
|
|
1432
1881
|
"select",
|
|
1433
1882
|
{
|
|
1434
1883
|
className: "cfi-vi-input",
|
|
@@ -1437,7 +1886,7 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1437
1886
|
onChange: (e) => {
|
|
1438
1887
|
if (e.target.value !== source.id) onOpenSource(e.target.value);
|
|
1439
1888
|
},
|
|
1440
|
-
children: allSources.slice().sort((a, b) => a.name.localeCompare(b.name)).map((s) => /* @__PURE__ */
|
|
1889
|
+
children: allSources.slice().sort((a, b) => a.name.localeCompare(b.name)).map((s) => /* @__PURE__ */ jsxs8("option", { value: s.id, children: [
|
|
1441
1890
|
s.name,
|
|
1442
1891
|
" (",
|
|
1443
1892
|
s.code,
|
|
@@ -1446,51 +1895,51 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1446
1895
|
] }, s.id))
|
|
1447
1896
|
}
|
|
1448
1897
|
),
|
|
1449
|
-
onBack && /* @__PURE__ */
|
|
1898
|
+
onBack && /* @__PURE__ */ jsx8("button", { type: "button", className: "cfi-vi-link cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-xs, 12px)" }, onClick: onBack, children: "All sources \u2192" })
|
|
1450
1899
|
] }),
|
|
1451
|
-
/* @__PURE__ */
|
|
1452
|
-
/* @__PURE__ */
|
|
1453
|
-
/* @__PURE__ */
|
|
1454
|
-
isOverlay && /* @__PURE__ */
|
|
1900
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", style: { flexWrap: "wrap", marginTop: 4 }, children: [
|
|
1901
|
+
/* @__PURE__ */ jsx8("h1", { className: "cfi-vi-h1", children: source.name }),
|
|
1902
|
+
/* @__PURE__ */ jsx8(Badge, { variant: "outline", children: source.code }),
|
|
1903
|
+
isOverlay && /* @__PURE__ */ jsx8(Badge, { variant: "purple", children: "Overlay" })
|
|
1455
1904
|
] }),
|
|
1456
|
-
/* @__PURE__ */
|
|
1905
|
+
/* @__PURE__ */ jsxs8("p", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-xs, 12px)", marginTop: 2 }, children: [
|
|
1457
1906
|
"Header row ",
|
|
1458
1907
|
source.headerRowIndex,
|
|
1459
1908
|
" \xB7 Format ",
|
|
1460
|
-
/* @__PURE__ */
|
|
1909
|
+
/* @__PURE__ */ jsx8("span", { className: "cfi-vi-mono", children: source.volumeHeaderFormat }),
|
|
1461
1910
|
" \xB7",
|
|
1462
1911
|
" ",
|
|
1463
|
-
source.layout === "tall" ? /* @__PURE__ */
|
|
1464
|
-
/* @__PURE__ */
|
|
1912
|
+
source.layout === "tall" ? /* @__PURE__ */ jsxs8("span", { className: "cfi-vi-row", style: { display: "inline-flex", gap: 4 }, children: [
|
|
1913
|
+
/* @__PURE__ */ jsx8(Rows, { size: 12, "aria-hidden": true }),
|
|
1465
1914
|
" tall"
|
|
1466
|
-
] }) : /* @__PURE__ */
|
|
1467
|
-
/* @__PURE__ */
|
|
1915
|
+
] }) : /* @__PURE__ */ jsxs8("span", { className: "cfi-vi-row", style: { display: "inline-flex", gap: 4 }, children: [
|
|
1916
|
+
/* @__PURE__ */ jsx8(Columns, { size: 12, "aria-hidden": true }),
|
|
1468
1917
|
" wide"
|
|
1469
1918
|
] }),
|
|
1470
|
-
source.layout === "tall" && /* @__PURE__ */
|
|
1919
|
+
source.layout === "tall" && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
1471
1920
|
" \xB7 Period ",
|
|
1472
|
-
/* @__PURE__ */
|
|
1921
|
+
/* @__PURE__ */ jsx8("span", { className: "cfi-vi-mono", children: source.valueDateFormat })
|
|
1473
1922
|
] }),
|
|
1474
|
-
source.description && /* @__PURE__ */
|
|
1923
|
+
source.description && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
1475
1924
|
" \xB7 ",
|
|
1476
1925
|
source.description
|
|
1477
1926
|
] })
|
|
1478
1927
|
] })
|
|
1479
1928
|
] }),
|
|
1480
|
-
hasData && /* @__PURE__ */
|
|
1481
|
-
/* @__PURE__ */
|
|
1929
|
+
hasData && /* @__PURE__ */ jsxs8("div", { className: "cfi-vi-lock", children: [
|
|
1930
|
+
/* @__PURE__ */ jsx8(Lock, { size: 14, "aria-hidden": true }),
|
|
1482
1931
|
" This source has loaded data. Configuration is locked \u2014 clear data below before making changes."
|
|
1483
1932
|
] }),
|
|
1484
|
-
/* @__PURE__ */
|
|
1485
|
-
/* @__PURE__ */
|
|
1486
|
-
/* @__PURE__ */
|
|
1487
|
-
editLayout === "tall" ? /* @__PURE__ */
|
|
1488
|
-
/* @__PURE__ */
|
|
1933
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-grid2", children: [
|
|
1934
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-panel", children: [
|
|
1935
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", children: [
|
|
1936
|
+
editLayout === "tall" ? /* @__PURE__ */ jsx8(Rows, { size: 16, className: "cfi-vi-muted", "aria-hidden": true }) : /* @__PURE__ */ jsx8(Columns, { size: 16, className: "cfi-vi-muted", "aria-hidden": true }),
|
|
1937
|
+
/* @__PURE__ */ jsx8("h2", { className: "cfi-vi-h2", children: "Layout" })
|
|
1489
1938
|
] }),
|
|
1490
|
-
/* @__PURE__ */
|
|
1491
|
-
/* @__PURE__ */
|
|
1492
|
-
/* @__PURE__ */
|
|
1493
|
-
/* @__PURE__ */
|
|
1939
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", style: { alignItems: "flex-end", gap: 12 }, children: [
|
|
1940
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-field", style: { flex: 1 }, children: [
|
|
1941
|
+
/* @__PURE__ */ jsx8("label", { className: "cfi-vi-label", children: "Layout" }),
|
|
1942
|
+
/* @__PURE__ */ jsxs8(
|
|
1494
1943
|
"select",
|
|
1495
1944
|
{
|
|
1496
1945
|
className: "cfi-vi-input",
|
|
@@ -1498,15 +1947,15 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1498
1947
|
disabled: hasData || savingLayout,
|
|
1499
1948
|
onChange: (e) => setEditLayout(e.target.value),
|
|
1500
1949
|
children: [
|
|
1501
|
-
/* @__PURE__ */
|
|
1502
|
-
/* @__PURE__ */
|
|
1950
|
+
/* @__PURE__ */ jsx8("option", { value: "wide", children: "wide" }),
|
|
1951
|
+
/* @__PURE__ */ jsx8("option", { value: "tall", children: "tall" })
|
|
1503
1952
|
]
|
|
1504
1953
|
}
|
|
1505
1954
|
)
|
|
1506
1955
|
] }),
|
|
1507
|
-
editLayout === "tall" && /* @__PURE__ */
|
|
1508
|
-
/* @__PURE__ */
|
|
1509
|
-
/* @__PURE__ */
|
|
1956
|
+
editLayout === "tall" && /* @__PURE__ */ jsxs8("div", { className: "cfi-vi-field", style: { flex: 1 }, children: [
|
|
1957
|
+
/* @__PURE__ */ jsx8("label", { className: "cfi-vi-label", children: "Period format" }),
|
|
1958
|
+
/* @__PURE__ */ jsx8(
|
|
1510
1959
|
TextInput,
|
|
1511
1960
|
{
|
|
1512
1961
|
className: "cfi-vi-mono",
|
|
@@ -1518,18 +1967,18 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1518
1967
|
)
|
|
1519
1968
|
] })
|
|
1520
1969
|
] }),
|
|
1521
|
-
/* @__PURE__ */
|
|
1970
|
+
/* @__PURE__ */ jsx8(Btn, { size: "sm", onClick: () => void saveLayoutAndRouting(), disabled: hasData || savingLayout, children: savingLayout ? "Saving\u2026" : "Save layout" })
|
|
1522
1971
|
] }),
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
/* @__PURE__ */
|
|
1526
|
-
/* @__PURE__ */
|
|
1527
|
-
keySegment && /* @__PURE__ */
|
|
1972
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-panel", children: [
|
|
1973
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", children: [
|
|
1974
|
+
/* @__PURE__ */ jsx8(KeyRound, { size: 16, className: "cfi-vi-muted", "aria-hidden": true }),
|
|
1975
|
+
/* @__PURE__ */ jsx8("h2", { className: "cfi-vi-h2", children: "Unique Key Column" }),
|
|
1976
|
+
keySegment && /* @__PURE__ */ jsx8(Badge, { variant: "secondary", children: keySegment.label })
|
|
1528
1977
|
] }),
|
|
1529
|
-
source.segments.length === 0 ? /* @__PURE__ */
|
|
1530
|
-
/* @__PURE__ */
|
|
1531
|
-
/* @__PURE__ */
|
|
1532
|
-
/* @__PURE__ */
|
|
1978
|
+
source.segments.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-xs, 12px)" }, children: "Detect segments first to enable this option." }) : /* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", style: { alignItems: "flex-end" }, children: [
|
|
1979
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-field", style: { flex: 1 }, children: [
|
|
1980
|
+
/* @__PURE__ */ jsx8("label", { className: "cfi-vi-label", children: "Key Segment" }),
|
|
1981
|
+
/* @__PURE__ */ jsxs8(
|
|
1533
1982
|
"select",
|
|
1534
1983
|
{
|
|
1535
1984
|
className: "cfi-vi-input",
|
|
@@ -1537,24 +1986,24 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1537
1986
|
disabled: hasData,
|
|
1538
1987
|
onChange: (e) => setSelectedKeyId(e.target.value),
|
|
1539
1988
|
children: [
|
|
1540
|
-
/* @__PURE__ */
|
|
1541
|
-
source.segments.slice().sort((a, b) => a.label.localeCompare(b.label)).map((seg) => /* @__PURE__ */
|
|
1989
|
+
/* @__PURE__ */ jsx8("option", { value: "__none__", children: "None \u2014 use display name" }),
|
|
1990
|
+
source.segments.slice().sort((a, b) => a.label.localeCompare(b.label)).map((seg) => /* @__PURE__ */ jsx8("option", { value: seg.id, children: seg.label }, seg.id))
|
|
1542
1991
|
]
|
|
1543
1992
|
}
|
|
1544
1993
|
)
|
|
1545
1994
|
] }),
|
|
1546
|
-
/* @__PURE__ */
|
|
1995
|
+
/* @__PURE__ */ jsx8(Btn, { size: "sm", onClick: saveUniqueKey, disabled: savingKey || hasData, children: savingKey ? "Saving\u2026" : "Save" })
|
|
1547
1996
|
] })
|
|
1548
1997
|
] })
|
|
1549
1998
|
] }),
|
|
1550
|
-
source.layout === "tall" && /* @__PURE__ */
|
|
1551
|
-
/* @__PURE__ */
|
|
1552
|
-
/* @__PURE__ */
|
|
1553
|
-
/* @__PURE__ */
|
|
1554
|
-
/* @__PURE__ */
|
|
1555
|
-
isOverlay && /* @__PURE__ */
|
|
1999
|
+
source.layout === "tall" && /* @__PURE__ */ jsx8(TallLayoutMappings, { transport, source, locked: hasData }),
|
|
2000
|
+
/* @__PURE__ */ jsxs8("div", { children: [
|
|
2001
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", children: [
|
|
2002
|
+
/* @__PURE__ */ jsx8(Layers, { size: 16, className: "cfi-vi-muted", "aria-hidden": true }),
|
|
2003
|
+
/* @__PURE__ */ jsx8("h2", { className: "cfi-vi-h2", children: "Segment Mapping" }),
|
|
2004
|
+
isOverlay && /* @__PURE__ */ jsx8("span", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-xs, 12px)" }, children: "\xB7 Map at least the levels your base source uses for the overlay merge to land." })
|
|
1556
2005
|
] }),
|
|
1557
|
-
source.segments.length === 0 ? /* @__PURE__ */
|
|
2006
|
+
source.segments.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "cfi-vi-muted", children: "No segments yet. Add segments below (Detect from file or Add manually) before mapping." }) : /* @__PURE__ */ jsx8(
|
|
1558
2007
|
UnifiedSegmentMapper,
|
|
1559
2008
|
{
|
|
1560
2009
|
segments: source.segments.slice().sort((a, b) => a.label.localeCompare(b.label)),
|
|
@@ -1570,16 +2019,16 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1570
2019
|
}
|
|
1571
2020
|
)
|
|
1572
2021
|
] }),
|
|
1573
|
-
/* @__PURE__ */
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
/* @__PURE__ */
|
|
1576
|
-
/* @__PURE__ */
|
|
2022
|
+
/* @__PURE__ */ jsx8(ValueAliasesCard, { transport, sourceId: source.id, locked: false, isOverlay }),
|
|
2023
|
+
/* @__PURE__ */ jsxs8("div", { children: [
|
|
2024
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", children: [
|
|
2025
|
+
/* @__PURE__ */ jsxs8("h2", { className: "cfi-vi-h2", children: [
|
|
1577
2026
|
"Segments (",
|
|
1578
2027
|
source.segments.length,
|
|
1579
2028
|
")"
|
|
1580
2029
|
] }),
|
|
1581
|
-
/* @__PURE__ */
|
|
1582
|
-
/* @__PURE__ */
|
|
2030
|
+
/* @__PURE__ */ jsx8(Btn, { variant: "outline", size: "sm", onClick: () => fileRef.current?.click(), disabled: detecting || hasData, children: detecting ? "Detecting\u2026" : "Detect from file" }),
|
|
2031
|
+
/* @__PURE__ */ jsx8(
|
|
1583
2032
|
"input",
|
|
1584
2033
|
{
|
|
1585
2034
|
ref: fileRef,
|
|
@@ -1594,14 +2043,14 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1594
2043
|
}
|
|
1595
2044
|
)
|
|
1596
2045
|
] }),
|
|
1597
|
-
detectMsg && /* @__PURE__ */
|
|
1598
|
-
error && /* @__PURE__ */
|
|
1599
|
-
/* @__PURE__ */
|
|
1600
|
-
/* @__PURE__ */
|
|
1601
|
-
/* @__PURE__ */
|
|
1602
|
-
/* @__PURE__ */
|
|
1603
|
-
/* @__PURE__ */
|
|
1604
|
-
/* @__PURE__ */
|
|
2046
|
+
detectMsg && /* @__PURE__ */ jsx8("p", { style: { fontSize: "var(--cfi-font-size-sm, 13px)", color: "#16a34a" }, children: detectMsg }),
|
|
2047
|
+
error && /* @__PURE__ */ jsx8("p", { className: "cfi-vi-error", children: error }),
|
|
2048
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-panel", style: { maxWidth: "42rem" }, children: [
|
|
2049
|
+
/* @__PURE__ */ jsx8("div", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-xs, 12px)" }, children: "Add segment manually \u2014 for columns not covered by auto-detect." }),
|
|
2050
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", style: { alignItems: "flex-end" }, children: [
|
|
2051
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-field", style: { flex: 1 }, children: [
|
|
2052
|
+
/* @__PURE__ */ jsx8("label", { className: "cfi-vi-label", children: "Label" }),
|
|
2053
|
+
/* @__PURE__ */ jsx8(
|
|
1605
2054
|
TextInput,
|
|
1606
2055
|
{
|
|
1607
2056
|
className: "cfi-vi-mono",
|
|
@@ -1615,9 +2064,9 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1615
2064
|
}
|
|
1616
2065
|
)
|
|
1617
2066
|
] }),
|
|
1618
|
-
/* @__PURE__ */
|
|
1619
|
-
/* @__PURE__ */
|
|
1620
|
-
/* @__PURE__ */
|
|
2067
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-field", style: { width: 128 }, children: [
|
|
2068
|
+
/* @__PURE__ */ jsx8("label", { className: "cfi-vi-label", children: "Data Type" }),
|
|
2069
|
+
/* @__PURE__ */ jsxs8(
|
|
1621
2070
|
"select",
|
|
1622
2071
|
{
|
|
1623
2072
|
className: "cfi-vi-input",
|
|
@@ -1625,33 +2074,33 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1625
2074
|
disabled: hasData || addingSegment,
|
|
1626
2075
|
onChange: (e) => setNewSegmentDataType(e.target.value),
|
|
1627
2076
|
children: [
|
|
1628
|
-
/* @__PURE__ */
|
|
1629
|
-
/* @__PURE__ */
|
|
1630
|
-
/* @__PURE__ */
|
|
2077
|
+
/* @__PURE__ */ jsx8("option", { value: "string", children: "string" }),
|
|
2078
|
+
/* @__PURE__ */ jsx8("option", { value: "number", children: "number" }),
|
|
2079
|
+
/* @__PURE__ */ jsx8("option", { value: "date", children: "date" })
|
|
1631
2080
|
]
|
|
1632
2081
|
}
|
|
1633
2082
|
)
|
|
1634
2083
|
] }),
|
|
1635
|
-
/* @__PURE__ */
|
|
2084
|
+
/* @__PURE__ */ jsx8(Btn, { size: "sm", onClick: () => void handleAddSegment(), disabled: hasData || addingSegment || !newSegmentLabel.trim(), children: addingSegment ? "Adding\u2026" : "Add segment" })
|
|
1636
2085
|
] })
|
|
1637
2086
|
] }),
|
|
1638
|
-
source.segments.length === 0 ? /* @__PURE__ */
|
|
1639
|
-
/* @__PURE__ */
|
|
1640
|
-
/* @__PURE__ */
|
|
1641
|
-
/* @__PURE__ */
|
|
1642
|
-
/* @__PURE__ */
|
|
1643
|
-
/* @__PURE__ */
|
|
1644
|
-
/* @__PURE__ */
|
|
2087
|
+
source.segments.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "cfi-vi-muted", children: "No segments yet. Upload a sample file to auto-detect." }) : /* @__PURE__ */ jsxs8("table", { className: "cfi-vi-table", children: [
|
|
2088
|
+
/* @__PURE__ */ jsx8("thead", { children: /* @__PURE__ */ jsxs8("tr", { children: [
|
|
2089
|
+
/* @__PURE__ */ jsx8("th", { style: { width: 48 }, children: "#" }),
|
|
2090
|
+
/* @__PURE__ */ jsx8("th", { children: "Label" }),
|
|
2091
|
+
/* @__PURE__ */ jsx8("th", { children: "Data Type" }),
|
|
2092
|
+
/* @__PURE__ */ jsx8("th", { style: { width: 80 }, children: "Key" }),
|
|
2093
|
+
/* @__PURE__ */ jsx8("th", { style: { width: 64 } })
|
|
1645
2094
|
] }) }),
|
|
1646
|
-
/* @__PURE__ */
|
|
1647
|
-
/* @__PURE__ */
|
|
1648
|
-
/* @__PURE__ */
|
|
1649
|
-
/* @__PURE__ */
|
|
1650
|
-
/* @__PURE__ */
|
|
1651
|
-
/* @__PURE__ */
|
|
2095
|
+
/* @__PURE__ */ jsx8("tbody", { children: source.segments.map((seg) => /* @__PURE__ */ jsxs8("tr", { children: [
|
|
2096
|
+
/* @__PURE__ */ jsx8("td", { className: "cfi-vi-muted", children: seg.sortOrder }),
|
|
2097
|
+
/* @__PURE__ */ jsx8("td", { className: "cfi-vi-mono", children: seg.label }),
|
|
2098
|
+
/* @__PURE__ */ jsx8("td", { className: "cfi-vi-muted", children: seg.dataType }),
|
|
2099
|
+
/* @__PURE__ */ jsx8("td", { children: seg.id === source.uniqueKeySegmentId && /* @__PURE__ */ jsxs8(Badge, { variant: "secondary", children: [
|
|
2100
|
+
/* @__PURE__ */ jsx8(KeyRound, { size: 12, "aria-hidden": true }),
|
|
1652
2101
|
" Key"
|
|
1653
2102
|
] }) }),
|
|
1654
|
-
/* @__PURE__ */
|
|
2103
|
+
/* @__PURE__ */ jsx8("td", { children: /* @__PURE__ */ jsx8(
|
|
1655
2104
|
"button",
|
|
1656
2105
|
{
|
|
1657
2106
|
type: "button",
|
|
@@ -1666,26 +2115,26 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1666
2115
|
] }, seg.id)) })
|
|
1667
2116
|
] })
|
|
1668
2117
|
] }),
|
|
1669
|
-
/* @__PURE__ */
|
|
1670
|
-
/* @__PURE__ */
|
|
1671
|
-
/* @__PURE__ */
|
|
1672
|
-
/* @__PURE__ */
|
|
2118
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-danger", children: [
|
|
2119
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", style: { color: "var(--cfi-color-error, #dc2626)" }, children: [
|
|
2120
|
+
/* @__PURE__ */ jsx8(AlertTriangle3, { size: 16, "aria-hidden": true }),
|
|
2121
|
+
/* @__PURE__ */ jsx8("h2", { className: "cfi-vi-h2", children: "Danger zone \u2014 clear source data" })
|
|
1673
2122
|
] }),
|
|
1674
|
-
/* @__PURE__ */
|
|
2123
|
+
/* @__PURE__ */ jsxs8("p", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-sm, 13px)" }, children: [
|
|
1675
2124
|
"Deletes every upload, criteria, volume actual, prediction, and forecast edit tied to",
|
|
1676
2125
|
" ",
|
|
1677
|
-
/* @__PURE__ */
|
|
2126
|
+
/* @__PURE__ */ jsx8("span", { className: "cfi-vi-mono", children: source.name }),
|
|
1678
2127
|
". Other sources are untouched. Configuration (segments, mappings, key column, layout) stays in place. There is no undo."
|
|
1679
2128
|
] }),
|
|
1680
|
-
/* @__PURE__ */
|
|
2129
|
+
/* @__PURE__ */ jsxs8("p", { className: "cfi-vi-muted", style: { fontSize: "var(--cfi-font-size-sm, 13px)" }, children: [
|
|
1681
2130
|
"To confirm, type ",
|
|
1682
|
-
/* @__PURE__ */
|
|
2131
|
+
/* @__PURE__ */ jsx8("span", { className: "cfi-vi-mono", style: { fontWeight: 600 }, children: "DELETE" }),
|
|
1683
2132
|
" below."
|
|
1684
2133
|
] }),
|
|
1685
|
-
/* @__PURE__ */
|
|
1686
|
-
/* @__PURE__ */
|
|
1687
|
-
/* @__PURE__ */
|
|
1688
|
-
/* @__PURE__ */
|
|
2134
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-row", style: { alignItems: "flex-end", maxWidth: "28rem" }, children: [
|
|
2135
|
+
/* @__PURE__ */ jsxs8("div", { className: "cfi-vi-field", style: { flex: 1 }, children: [
|
|
2136
|
+
/* @__PURE__ */ jsx8("label", { className: "cfi-vi-label", children: "Confirmation" }),
|
|
2137
|
+
/* @__PURE__ */ jsx8(
|
|
1689
2138
|
TextInput,
|
|
1690
2139
|
{
|
|
1691
2140
|
className: "cfi-vi-mono",
|
|
@@ -1696,9 +2145,9 @@ function VolumeSourceDetail({ transport, sourceId, onOpenSource, onBack, classNa
|
|
|
1696
2145
|
}
|
|
1697
2146
|
)
|
|
1698
2147
|
] }),
|
|
1699
|
-
/* @__PURE__ */
|
|
2148
|
+
/* @__PURE__ */ jsx8(Btn, { variant: "destructive", size: "sm", onClick: () => void handleClearData(), disabled: clearConfirm !== "DELETE" || clearing, children: clearing ? "Clearing\u2026" : "Clear all data" })
|
|
1700
2149
|
] }),
|
|
1701
|
-
clearResult && /* @__PURE__ */
|
|
2150
|
+
clearResult && /* @__PURE__ */ jsx8("p", { style: { fontSize: "var(--cfi-font-size-sm, 13px)", color: "#15803d" }, children: clearResult })
|
|
1702
2151
|
] })
|
|
1703
2152
|
] }) });
|
|
1704
2153
|
}
|
|
@@ -1710,6 +2159,7 @@ export {
|
|
|
1710
2159
|
TallLayoutMappings,
|
|
1711
2160
|
UnifiedSegmentMapper,
|
|
1712
2161
|
ValueAliasesCard,
|
|
2162
|
+
VolumeFiles,
|
|
1713
2163
|
VolumeImport,
|
|
1714
2164
|
VolumeSourceDetail,
|
|
1715
2165
|
VolumeSourcesList
|