@gen-epix/ui-client-casedb 4.1.0 → 4.3.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.
Files changed (63) hide show
  1. package/dist/_chunks/AddCasesToEventDialog.js +98 -98
  2. package/dist/_chunks/AddCasesToEventDialog.js.map +1 -1
  3. package/dist/_chunks/CaseContentForm.js +10 -10
  4. package/dist/_chunks/CaseInfoDialog.js +242 -241
  5. package/dist/_chunks/CaseInfoDialog.js.map +1 -1
  6. package/dist/_chunks/CaseSetInfoDialog.js +224 -224
  7. package/dist/_chunks/CaseSetInfoDialog.js.map +1 -1
  8. package/dist/_chunks/Dashboard.js +549 -550
  9. package/dist/_chunks/Dashboard.js.map +1 -1
  10. package/dist/_chunks/FindSimilarCasesDialog.js +76 -76
  11. package/dist/_chunks/FindSimilarCasesDialog.js.map +1 -1
  12. package/dist/_chunks/LegendaItem.js.map +1 -1
  13. package/dist/_chunks/LineListWidget.js +138 -136
  14. package/dist/_chunks/LineListWidget.js.map +1 -1
  15. package/dist/_chunks/PanelSeparator.js +3 -3
  16. package/dist/_chunks/PanelSeparator.js.map +1 -1
  17. package/dist/_chunks/Upload.js +318 -318
  18. package/dist/_chunks/Upload.js.map +1 -1
  19. package/dist/_chunks/{chunk-BV7QT456.js → chunk-OB3PAWPO.js} +3 -3
  20. package/dist/_chunks/chunk-OB3PAWPO.js.map +1 -0
  21. package/dist/_chunks/cloneDeep.js +1 -1
  22. package/dist/_chunks/cloneDeep.js.map +1 -1
  23. package/dist/_chunks/esm.js +3 -3
  24. package/dist/_chunks/esm.js.map +1 -1
  25. package/dist/_chunks/index.module.js +1 -1
  26. package/dist/_chunks/index.module.js.map +1 -1
  27. package/dist/_chunks/react.js +1 -1
  28. package/dist/_chunks/react.js.map +1 -1
  29. package/dist/_chunks/shallow.js +2 -2
  30. package/dist/_chunks/shallow.js.map +1 -1
  31. package/dist/_chunks/vanilla.js +1 -1
  32. package/dist/_chunks/vanilla.js.map +1 -1
  33. package/dist/_chunks/yup.js +24 -24
  34. package/dist/_chunks/yup.js.map +1 -1
  35. package/dist/components/form/fields/ArrangementEditor/index.js +30 -30
  36. package/dist/components/ui/CreateEventDialog/index.js +40 -40
  37. package/dist/components/ui/CreateEventDialog/index.js.map +1 -1
  38. package/dist/components/ui/HistogramWidget/index.js +161 -162
  39. package/dist/components/ui/HistogramWidget/index.js.map +1 -1
  40. package/dist/components/ui/SequenceDownloadDialog/index.js +22 -22
  41. package/dist/locale/en.json +6 -0
  42. package/dist/locale/nl.json +7 -1
  43. package/dist/pages/CasesDetailPage/index.js +1 -1
  44. package/dist/pages/ColsAdminPage/index.js +1 -1
  45. package/dist/pages/ConceptsAdminPage/index.js +1 -1
  46. package/dist/pages/DimsAdminPage/index.js +1 -1
  47. package/dist/pages/EventsDetailPage/index.js +1 -1
  48. package/dist/pages/OrganizationAccessCasePoliciesAdminPage/index.js +120 -86
  49. package/dist/pages/OrganizationAccessCasePoliciesAdminPage/index.js.map +1 -1
  50. package/dist/pages/RefColsAdminPage/index.js +1 -1
  51. package/dist/pages/RegionSetShapesAdminPage/index.js +1 -1
  52. package/dist/pages/RegionsAdminPage/index.js +1 -1
  53. package/dist/pages/UserEffectiveRightsAdminPage/index.js +1 -1
  54. package/dist/pages/UserEffectiveRightsTesterAdminPage/index.js +59 -59
  55. package/dist/pages/UserEffectiveRightsTesterAdminPage/index.js.map +1 -1
  56. package/dist/routes/index.js +93 -91
  57. package/dist/routes/index.js.map +1 -1
  58. package/dist/setup/setup.js +2 -3
  59. package/dist/setup/setup.js.map +1 -1
  60. package/package.json +73 -72
  61. package/dist/_chunks/chunk-BV7QT456.js.map +0 -1
  62. package/dist/_chunks/index.esm.js +0 -1465
  63. package/dist/_chunks/index.esm.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/ui/HistogramWidget/HistogramWidget.tsx"],"sourcesContent":["import { Box } from '@mui/system';\nimport type { ReactElement } from 'react';\nimport {\n use,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { EChartsType } from 'echarts';\nimport {\n LegendComponent,\n TooltipComponent,\n} from 'echarts/components';\nimport {\n dispose,\n getInstanceByDom,\n init,\n use as registerECharts,\n} from 'echarts/core';\nimport type { EChartsReactProps } from 'echarts-for-react';\nimport FilterAltIcon from '@mui/icons-material/FilterAlt';\nimport EChartsReact from 'echarts-for-react';\nimport type {\n CaseDbCol,\n CaseDbColType,\n} from '@gen-epix/api-casedb';\nimport type { MenuItemData } from '@gen-epix/ui-core-components/models/nestedMenu';\nimport { ConfigService } from '@gen-epix/ui-client-common/classes/services/ConfigService';\nimport { useStore } from 'zustand';\nimport { BarChart } from 'echarts/charts';\nimport { CanvasRenderer } from 'echarts/renderers';\nimport { useTranslation } from 'react-i18next';\nimport round from 'lodash/round';\nimport {\n ListItemIcon,\n ListItemText,\n MenuItem,\n useTheme,\n} from '@mui/material';\nimport intersection from 'lodash/intersection';\n\nimport { DASHBOARD_COMPONENT_NAME } from '../../../constants/dashboard';\nimport type { ContextMenuConfigWithPosition } from '../ContextMenu';\nimport { ContextMenu } from '../ContextMenu';\nimport { DashboardWidget } from '../Dashboard';\nimport { WidgetUnavailable } from '../WidgetUnavailable';\nimport { DashboardStoreContext } from '../../../stores/dashboardStore';\nimport { DashboardUtil } from '../../../utils/DashboardUtil';\nimport { EventBusService } from '../../../classes/services/EventBusService';\nimport { CaseDbDownloadUtil } from '../../../utils/CaseDbDownloadUtil';\nimport type { HistogramWidgetData } from '../../../models/dashboard';\nimport {\n HISTOGRAM_ALLOWED_COL_TYPES,\n HistogramUtil,\n} from '../../../utils/HistogramUtil';\nimport { DashboardContext } from '../Dashboard/context/DashboardContext';\nimport { CaseUtil } from '../../../utils/CaseUtil';\n\nregisterECharts([TooltipComponent, BarChart, LegendComponent, CanvasRenderer]);\n\nconst echartsCore = {\n dispose,\n getInstanceByDom,\n init,\n};\n\nexport const HistogramWidget = () => {\n const { t } = useTranslation();\n const theme = useTheme();\n const chartRef = useRef<EChartsReact>(null);\n const chartInstanceRef = useRef<EChartsType | null>(null);\n const echartsOpts = useMemo(() => ({\n nonce: ConfigService.getInstance().config.nonce,\n }), []);\n const dashboardStore = use(DashboardStoreContext);\n const dashboardContext = use(DashboardContext);\n const completeCaseType = useStore(dashboardStore, (state) => state.completeCaseType);\n const sortedData = useStore(dashboardStore, (state) => state.sortedData);\n const setFilterValues = useStore(dashboardStore, (state) => state.setFilterValues);\n const updateWidgetData = useStore(dashboardStore, (state) => state.updateWidgetData);\n const histogramWidgetData = useStore(dashboardStore, (state) => state.getWidgetData<HistogramWidgetData>(DASHBOARD_COMPONENT_NAME.HISTOGRAM));\n const [focussedColValues, setFocussedColValues] = useState<{ a: string; b: string }>(null);\n\n const allowedColTypes = useMemo<CaseDbColType[]>(() => {\n return HISTOGRAM_ALLOWED_COL_TYPES;\n }, []);\n\n const allowedCols = useMemo(() => {\n return HistogramUtil.getAllowedCols(completeCaseType, allowedColTypes);\n }, [allowedColTypes, completeCaseType]);\n\n const [aCol, setACol] = useState<CaseDbCol | null>(histogramWidgetData.colAId ? completeCaseType?.cols[histogramWidgetData.colAId] ?? null : null);\n const [bCol, setBCol] = useState<CaseDbCol | null>(histogramWidgetData.colBId ? completeCaseType?.cols[histogramWidgetData.colBId] ?? null : null);\n\n const [contextMenuConfig, setContextMenuConfig] = useState<ContextMenuConfigWithPosition | null>(null);\n\n const onEpiContextMenuClose = useCallback(() => {\n setContextMenuConfig(null);\n setFocussedColValues(null);\n }, []);\n\n const lineListCaseCount = useMemo(() => {\n return DashboardUtil.getCaseCount(sortedData);\n }, [sortedData]);\n\n const defaultCols = useMemo(() => {\n return HistogramUtil.getDefaultCols(allowedCols, completeCaseType);\n }, [allowedCols, completeCaseType]);\n\n\n const canShowWidget = allowedCols.length > 1 && defaultCols?.newColA && defaultCols?.newColB;\n const shouldShowGraph = canShowWidget && aCol && bCol && lineListCaseCount > 0;\n\n const onMenuItemClick = useCallback((x: CaseDbCol, y: CaseDbCol) => {\n setACol(x);\n setBCol(y);\n updateWidgetData(DASHBOARD_COMPONENT_NAME.HISTOGRAM, {\n colAId: x.id,\n colBId: y.id,\n });\n }, [updateWidgetData]);\n\n\n useEffect(() => {\n if (aCol && bCol) {\n return;\n }\n if (!defaultCols) {\n return;\n }\n const { newColA, newColB } = defaultCols;\n\n setACol(newColA);\n setBCol(newColB);\n\n updateWidgetData(DASHBOARD_COMPONENT_NAME.HISTOGRAM, {\n colAId: newColA.id,\n colBId: newColB.id,\n });\n }, [aCol, allowedCols, bCol, completeCaseType, defaultCols, updateWidgetData]);\n\n const [conceptsA, conceptsB] = useMemo(() => {\n return HistogramUtil.getConcepts(aCol, bCol, completeCaseType);\n }, [aCol, bCol, completeCaseType]);\n\n const series = useMemo(() => {\n return HistogramUtil.getSeries(aCol, bCol, completeCaseType, sortedData, conceptsA, conceptsB);\n }, [aCol, bCol, completeCaseType, sortedData, conceptsA, conceptsB]);\n\n const histogramCaseCount = useMemo(() => {\n return HistogramUtil.getCaseCount(series);\n }, [series]);\n\n const missingCasesCount = lineListCaseCount - histogramCaseCount;\n const missingCasesPercentage = missingCasesCount > 0 ? round(missingCasesCount / lineListCaseCount * 100, 1) : 0;\n\n const widgetUnavailableReason = useMemo<ReactElement | string>(() => {\n if (shouldShowGraph) {\n return;\n }\n if (!defaultCols || allowedCols.length < 2) {\n return t`No two compatible columns found to display a histogram.`;\n }\n if (!lineListCaseCount) {\n return t`No cases found.`;\n }\n if (!histogramCaseCount) {\n return t`No cases found with valid values for the selected columns to display a histogram.`;\n }\n return null;\n }, [allowedCols.length, defaultCols, histogramCaseCount, lineListCaseCount, shouldShowGraph, t]);\n\n const colors = useMemo(() => {\n return HistogramUtil.getColors(aCol, completeCaseType, sortedData);\n }, [completeCaseType, aCol, sortedData]);\n\n const getOptions = useCallback(() => {\n if (!shouldShowGraph) {\n return null;\n }\n\n return HistogramUtil.getChartOptions({\n aCol,\n bCol,\n colors,\n conceptsA,\n conceptsB,\n series,\n t,\n theme,\n });\n }, [shouldShowGraph, colors, theme, conceptsB, series, conceptsA, aCol, bCol, t]);\n\n const titleMenu = useMemo<MenuItemData | string>(() => {\n let label: string;\n if (aCol && bCol) {\n label = t('Histogram: {{aColLabel}} and {{bColLabel}}', { aColLabel: aCol.label, bColLabel: bCol.label });\n } else {\n label = t`Histogram`;\n }\n\n if (!defaultCols?.newColA || !defaultCols?.newColB) {\n return label;\n }\n\n const mainMenu: MenuItemData = {\n disabled: !canShowWidget || allowedCols.length < 2,\n items: [],\n label,\n };\n\n\n allowedCols.forEach(x => {\n const subMenu: MenuItemData = {\n active: aCol?.id === x.id || undefined,\n items: [],\n label: t('Grouping: {{label}}', { label: x.label }),\n };\n allowedCols.forEach(y => {\n if (x.id === y.id) {\n return;\n }\n subMenu.items.push({\n active: (aCol?.id === x.id || undefined) && (bCol?.id === y.id || undefined),\n callback: () => {\n onMenuItemClick(x, y);\n },\n label: t('X-Axis: {{label}}', { label: y.label }),\n });\n });\n mainMenu.items.push(subMenu);\n });\n\n\n return mainMenu;\n }, [aCol, bCol, canShowWidget, allowedCols, defaultCols?.newColA, defaultCols?.newColB, t, onMenuItemClick]);\n\n const onChartReady = useCallback((chart: EChartsType) => {\n chartInstanceRef.current = chart;\n if (!aCol || !bCol) {\n return;\n }\n const dom = chart.getDom();\n dom?.setAttribute('aria-label', t('Histogram showing the number of cases for {{aColLabel}} and {{bColLabel}}', { aColLabel: aCol?.label, bColLabel: bCol?.label }));\n dom?.setAttribute('role', 'img');\n }, [aCol, bCol, t]);\n\n\n useEffect(() => {\n const emitDownloadOptions = () => {\n EventBusService.getInstance().emit('onDownloadOptionsChanged', {\n disabled: !canShowWidget,\n items: [\n {\n callback: () => CaseDbDownloadUtil.downloadEchartsImage(t`Histogram`, chartRef.current.getEchartsInstance(), 'png', completeCaseType, t),\n disabled: !shouldShowGraph,\n label: t`Save as PNG`,\n },\n {\n callback: () => CaseDbDownloadUtil.downloadEchartsImage(t`Histogram`, chartRef.current.getEchartsInstance(), 'jpeg', completeCaseType, t),\n disabled: !shouldShowGraph,\n label: t`Save as JPEG`,\n },\n ],\n zone: DASHBOARD_COMPONENT_NAME.HISTOGRAM,\n zoneLabel: t`Histogram`,\n });\n };\n emitDownloadOptions();\n const eventBusManager = EventBusService.getInstance();\n eventBusManager.addEventListener('onDownloadOptionsRequested', emitDownloadOptions);\n return () => {\n eventBusManager.emit('onDownloadOptionsChanged', {\n items: null,\n zone: DASHBOARD_COMPONENT_NAME.HISTOGRAM,\n zoneLabel: t`Histogram`,\n });\n eventBusManager.removeEventListener('onDownloadOptionsRequested', emitDownloadOptions);\n };\n }, [completeCaseType, shouldShowGraph, canShowWidget, t]);\n\n const highlight = useCallback((caseIds: string[]) => {\n dashboardContext.highlight({\n caseIds,\n origin: DASHBOARD_COMPONENT_NAME.HISTOGRAM,\n });\n }, [dashboardContext]);\n\n const onEvents = useMemo<EChartsReactProps['onEvents']>(() => {\n\n const getCaseIdsFromPayload = (payload: unknown): string[] => {\n const colValues = HistogramUtil.getColValuesFromPayload(payload, conceptsA, conceptsB);\n if (!colValues) {\n return [];\n }\n const caseIds = sortedData.filter(caseDbCase => {\n const aValue = CaseUtil.getRowValue(caseDbCase.content, aCol, completeCaseType);\n const bValue = CaseUtil.getRowValue(caseDbCase.content, bCol, completeCaseType);\n return colValues.a === aValue.raw && colValues.b === bValue.raw;\n }).map(caseDbCase => caseDbCase.id);\n return caseIds;\n };\n\n return {\n globalout: () => {\n highlight([]);\n },\n mouseout: () => {\n highlight([]);\n },\n mouseover: (payload: unknown) => {\n highlight(getCaseIdsFromPayload(payload));\n },\n mouseup: (payload: unknown) => {\n const { event } = payload as { event: { event: MouseEvent } };\n setFocussedColValues(HistogramUtil.getColValuesFromPayload(payload, conceptsA, conceptsB));\n setContextMenuConfig({\n caseIds: getCaseIdsFromPayload(payload),\n mouseEvent: event.event,\n position: {\n left: (event.event).clientX,\n top: (event.event).clientY,\n },\n });\n },\n };\n }, [aCol, bCol, completeCaseType, conceptsA, conceptsB, highlight, sortedData]);\n\n const onShowOnlyFocussedColValuesMenuItemClick = useCallback(async (onMenuClose: () => void) => {\n if (!focussedColValues || !aCol || !bCol) {\n return;\n }\n await setFilterValues({\n [aCol.id]: [focussedColValues.a],\n [bCol.id]: [focussedColValues.b],\n });\n\n onMenuClose();\n }, [aCol, bCol, focussedColValues, setFilterValues]);\n\n const getEpiContextMenuExtraItems = useCallback((onMenuClose: () => void): ReactElement => {\n const conceptALabel = conceptsA.find(concept => concept.id === focussedColValues?.a)?.name;\n const conceptBLabel = conceptsB.find(concept => concept.id === focussedColValues?.b)?.name;\n if (!conceptALabel || !conceptBLabel) {\n return null;\n }\n if (!focussedColValues) {\n return null;\n }\n return (\n <MenuItem\n divider\n // eslint-disable-next-line @eslint-react/kit/jsx-no-bind\n onClick={async () => await onShowOnlyFocussedColValuesMenuItemClick(onMenuClose)}\n >\n <ListItemIcon>\n <FilterAltIcon fontSize={'small'} />\n </ListItemIcon>\n <ListItemText>\n {t('Filter (show only {{conceptALabel}} and {{conceptBLabel}})', { conceptALabel, conceptBLabel })}\n </ListItemText>\n </MenuItem>\n );\n }, [conceptsA, conceptsB, focussedColValues, onShowOnlyFocussedColValuesMenuItemClick, t]);\n\n useEffect(() => {\n const unsubscribe = dashboardContext.highlightSubject.subscribe((highlighting) => {\n if (highlighting.origin === DASHBOARD_COMPONENT_NAME.HISTOGRAM) {\n return;\n }\n const instance = chartInstanceRef.current;\n if (!instance) {\n return;\n }\n\n if (!highlighting?.caseIds?.length) {\n instance.dispatchAction({\n type: 'downplay',\n });\n return;\n }\n\n const highlightTargetsByDataIndex = new Map<number, Set<number>>();\n series?.forEach((serie, serieIndex) => {\n const castedSerie = serie as { data: unknown[]; xCaseIds: string[][] };\n castedSerie.xCaseIds?.forEach((caseIds: string[], dataIndex: number) => {\n if (intersection(caseIds, highlighting.caseIds).length) {\n const seriesIndices = highlightTargetsByDataIndex.get(dataIndex) ?? new Set<number>();\n seriesIndices.add(serieIndex);\n highlightTargetsByDataIndex.set(dataIndex, seriesIndices);\n }\n });\n });\n\n instance.dispatchAction({\n type: 'downplay',\n });\n\n const highlightBatch: Array<{ dataIndex: number; notBlur?: boolean; seriesIndex?: number }> = [];\n highlightTargetsByDataIndex.forEach((seriesIndices, dataIndex) => {\n if (seriesIndices.size === series?.length) {\n highlightBatch.push({\n dataIndex,\n });\n return;\n }\n\n seriesIndices.forEach((seriesIndex) => {\n highlightBatch.push({\n dataIndex,\n seriesIndex,\n });\n });\n });\n\n highlightBatch.forEach((target, index) => {\n if (index > 0) {\n target.notBlur = true;\n }\n });\n\n instance.dispatchAction({\n batch: highlightBatch,\n type: 'highlight',\n });\n });\n\n return () => {\n unsubscribe();\n };\n }, [dashboardContext, series]);\n\n return (\n <DashboardWidget\n expandDisabled={!canShowWidget}\n title={titleMenu}\n warningMessage={canShowWidget && histogramCaseCount > 0 && missingCasesCount > 0 ? t('Missing cases: {{missingCasesCount}} ({{missingCasesPercentage}}%)', { missingCasesCount, missingCasesPercentage }) : undefined}\n widgetName={DASHBOARD_COMPONENT_NAME.HISTOGRAM}\n >\n {!canShowWidget && (\n <WidgetUnavailable\n reason={widgetUnavailableReason}\n widgetLabel={t`histogram`}\n />\n )}\n {canShowWidget && (\n <Box\n sx={{\n height: '100%',\n position: 'relative',\n }}\n >\n {shouldShowGraph && (\n <EChartsReact\n echarts={echartsCore}\n notMerge\n onChartReady={onChartReady}\n onEvents={onEvents}\n option={getOptions()}\n opts={echartsOpts as unknown}\n ref={chartRef}\n style={{\n height: '100%',\n position: 'absolute',\n width: '100%',\n }}\n />\n )}\n <ContextMenu\n config={contextMenuConfig}\n getExtraItems={getEpiContextMenuExtraItems}\n onMenuClose={onEpiContextMenuClose}\n />\n </Box>\n )}\n </DashboardWidget>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/ui/HistogramWidget/HistogramWidget.tsx"],"sourcesContent":["import {\n Box,\n ListItemIcon,\n ListItemText,\n MenuItem,\n useTheme,\n} from '@mui/material';\nimport type { ReactElement } from 'react';\nimport {\n use,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { EChartsType } from 'echarts';\nimport {\n LegendComponent,\n TooltipComponent,\n} from 'echarts/components';\nimport {\n dispose,\n getInstanceByDom,\n init,\n use as registerECharts,\n} from 'echarts/core';\nimport type { EChartsReactProps } from 'echarts-for-react';\nimport FilterAltIcon from '@mui/icons-material/FilterAlt';\nimport EChartsReact from 'echarts-for-react';\nimport type {\n CaseDbCol,\n CaseDbColType,\n} from '@gen-epix/api-casedb';\nimport type { MenuItemData } from '@gen-epix/ui-core-components/models/nestedMenu';\nimport { ConfigService } from '@gen-epix/ui-client-common/classes/services/ConfigService';\nimport { useStore } from 'zustand';\nimport { BarChart } from 'echarts/charts';\nimport { CanvasRenderer } from 'echarts/renderers';\nimport { useTranslation } from 'react-i18next';\nimport round from 'lodash/round';\nimport intersection from 'lodash/intersection';\n\nimport { DASHBOARD_COMPONENT_NAME } from '../../../constants/dashboard';\nimport type { ContextMenuConfigWithPosition } from '../ContextMenu';\nimport { ContextMenu } from '../ContextMenu';\nimport { DashboardWidget } from '../Dashboard';\nimport { WidgetUnavailable } from '../WidgetUnavailable';\nimport { DashboardStoreContext } from '../../../stores/dashboardStore';\nimport { DashboardUtil } from '../../../utils/DashboardUtil';\nimport { EventBusService } from '../../../classes/services/EventBusService';\nimport { CaseDbDownloadUtil } from '../../../utils/CaseDbDownloadUtil';\nimport type { HistogramWidgetData } from '../../../models/dashboard';\nimport {\n HISTOGRAM_ALLOWED_COL_TYPES,\n HistogramUtil,\n} from '../../../utils/HistogramUtil';\nimport { DashboardContext } from '../Dashboard/context/DashboardContext';\nimport { CaseUtil } from '../../../utils/CaseUtil';\n\nregisterECharts([TooltipComponent, BarChart, LegendComponent, CanvasRenderer]);\n\nconst echartsCore = {\n dispose,\n getInstanceByDom,\n init,\n};\n\nexport const HistogramWidget = () => {\n const { t } = useTranslation();\n const theme = useTheme();\n const chartRef = useRef<EChartsReact>(null);\n const chartInstanceRef = useRef<EChartsType | null>(null);\n const echartsOpts = useMemo(() => ({\n nonce: ConfigService.getInstance().config.nonce,\n }), []);\n const dashboardStore = use(DashboardStoreContext);\n const dashboardContext = use(DashboardContext);\n const completeCaseType = useStore(dashboardStore, (state) => state.completeCaseType);\n const sortedData = useStore(dashboardStore, (state) => state.sortedData);\n const setFilterValues = useStore(dashboardStore, (state) => state.setFilterValues);\n const updateWidgetData = useStore(dashboardStore, (state) => state.updateWidgetData);\n const histogramWidgetData = useStore(dashboardStore, (state) => state.getWidgetData<HistogramWidgetData>(DASHBOARD_COMPONENT_NAME.HISTOGRAM));\n const [focussedColValues, setFocussedColValues] = useState<{ a: string; b: string }>(null);\n\n const allowedColTypes = useMemo<CaseDbColType[]>(() => {\n return HISTOGRAM_ALLOWED_COL_TYPES;\n }, []);\n\n const allowedCols = useMemo(() => {\n return HistogramUtil.getAllowedCols(completeCaseType, allowedColTypes);\n }, [allowedColTypes, completeCaseType]);\n\n const [aCol, setACol] = useState<CaseDbCol | null>(histogramWidgetData.colAId ? completeCaseType?.cols[histogramWidgetData.colAId] ?? null : null);\n const [bCol, setBCol] = useState<CaseDbCol | null>(histogramWidgetData.colBId ? completeCaseType?.cols[histogramWidgetData.colBId] ?? null : null);\n\n const [contextMenuConfig, setContextMenuConfig] = useState<ContextMenuConfigWithPosition | null>(null);\n\n const onEpiContextMenuClose = useCallback(() => {\n setContextMenuConfig(null);\n setFocussedColValues(null);\n }, []);\n\n const lineListCaseCount = useMemo(() => {\n return DashboardUtil.getCaseCount(sortedData);\n }, [sortedData]);\n\n const defaultCols = useMemo(() => {\n return HistogramUtil.getDefaultCols(allowedCols, completeCaseType);\n }, [allowedCols, completeCaseType]);\n\n\n const canShowWidget = allowedCols.length > 1 && defaultCols?.newColA && defaultCols?.newColB;\n const shouldShowGraph = canShowWidget && aCol && bCol && lineListCaseCount > 0;\n\n const onMenuItemClick = useCallback((x: CaseDbCol, y: CaseDbCol) => {\n setACol(x);\n setBCol(y);\n updateWidgetData(DASHBOARD_COMPONENT_NAME.HISTOGRAM, {\n colAId: x.id,\n colBId: y.id,\n });\n }, [updateWidgetData]);\n\n\n useEffect(() => {\n if (aCol && bCol) {\n return;\n }\n if (!defaultCols) {\n return;\n }\n const { newColA, newColB } = defaultCols;\n\n setACol(newColA);\n setBCol(newColB);\n\n updateWidgetData(DASHBOARD_COMPONENT_NAME.HISTOGRAM, {\n colAId: newColA.id,\n colBId: newColB.id,\n });\n }, [aCol, allowedCols, bCol, completeCaseType, defaultCols, updateWidgetData]);\n\n const [conceptsA, conceptsB] = useMemo(() => {\n return HistogramUtil.getConcepts(aCol, bCol, completeCaseType);\n }, [aCol, bCol, completeCaseType]);\n\n const series = useMemo(() => {\n return HistogramUtil.getSeries(aCol, bCol, completeCaseType, sortedData, conceptsA, conceptsB);\n }, [aCol, bCol, completeCaseType, sortedData, conceptsA, conceptsB]);\n\n const histogramCaseCount = useMemo(() => {\n return HistogramUtil.getCaseCount(series);\n }, [series]);\n\n const missingCasesCount = lineListCaseCount - histogramCaseCount;\n const missingCasesPercentage = missingCasesCount > 0 ? round(missingCasesCount / lineListCaseCount * 100, 1) : 0;\n\n const widgetUnavailableReason = useMemo<ReactElement | string>(() => {\n if (shouldShowGraph) {\n return;\n }\n if (!defaultCols || allowedCols.length < 2) {\n return t`No two compatible columns found to display a histogram.`;\n }\n if (!lineListCaseCount) {\n return t`No cases found.`;\n }\n if (!histogramCaseCount) {\n return t`No cases found with valid values for the selected columns to display a histogram.`;\n }\n return null;\n }, [allowedCols.length, defaultCols, histogramCaseCount, lineListCaseCount, shouldShowGraph, t]);\n\n const colors = useMemo(() => {\n return HistogramUtil.getColors(aCol, completeCaseType, sortedData);\n }, [completeCaseType, aCol, sortedData]);\n\n const getOptions = useCallback(() => {\n if (!shouldShowGraph) {\n return null;\n }\n\n return HistogramUtil.getChartOptions({\n aCol,\n bCol,\n colors,\n conceptsA,\n conceptsB,\n series,\n t,\n theme,\n });\n }, [shouldShowGraph, colors, theme, conceptsB, series, conceptsA, aCol, bCol, t]);\n\n const titleMenu = useMemo<MenuItemData | string>(() => {\n let label: string;\n if (aCol && bCol) {\n label = t('Histogram: {{aColLabel}} and {{bColLabel}}', { aColLabel: aCol.label, bColLabel: bCol.label });\n } else {\n label = t`Histogram`;\n }\n\n if (!defaultCols?.newColA || !defaultCols?.newColB) {\n return label;\n }\n\n const mainMenu: MenuItemData = {\n disabled: !canShowWidget || allowedCols.length < 2,\n items: [],\n label,\n };\n\n\n allowedCols.forEach(x => {\n const subMenu: MenuItemData = {\n active: aCol?.id === x.id || undefined,\n items: [],\n label: t('Grouping: {{label}}', { label: x.label }),\n };\n allowedCols.forEach(y => {\n if (x.id === y.id) {\n return;\n }\n subMenu.items.push({\n active: (aCol?.id === x.id || undefined) && (bCol?.id === y.id || undefined),\n callback: () => {\n onMenuItemClick(x, y);\n },\n label: t('X-Axis: {{label}}', { label: y.label }),\n });\n });\n mainMenu.items.push(subMenu);\n });\n\n\n return mainMenu;\n }, [aCol, bCol, canShowWidget, allowedCols, defaultCols?.newColA, defaultCols?.newColB, t, onMenuItemClick]);\n\n const onChartReady = useCallback((chart: EChartsType) => {\n chartInstanceRef.current = chart;\n if (!aCol || !bCol) {\n return;\n }\n const dom = chart.getDom();\n dom?.setAttribute('aria-label', t('Histogram showing the number of cases for {{aColLabel}} and {{bColLabel}}', { aColLabel: aCol?.label, bColLabel: bCol?.label }));\n dom?.setAttribute('role', 'img');\n }, [aCol, bCol, t]);\n\n\n useEffect(() => {\n const emitDownloadOptions = () => {\n EventBusService.getInstance().emit('onDownloadOptionsChanged', {\n disabled: !canShowWidget,\n items: [\n {\n callback: () => CaseDbDownloadUtil.downloadEchartsImage(t`Histogram`, chartRef.current.getEchartsInstance(), 'png', completeCaseType, t),\n disabled: !shouldShowGraph,\n label: t`Save as PNG`,\n },\n {\n callback: () => CaseDbDownloadUtil.downloadEchartsImage(t`Histogram`, chartRef.current.getEchartsInstance(), 'jpeg', completeCaseType, t),\n disabled: !shouldShowGraph,\n label: t`Save as JPEG`,\n },\n ],\n zone: DASHBOARD_COMPONENT_NAME.HISTOGRAM,\n zoneLabel: t`Histogram`,\n });\n };\n emitDownloadOptions();\n const eventBusManager = EventBusService.getInstance();\n eventBusManager.addEventListener('onDownloadOptionsRequested', emitDownloadOptions);\n return () => {\n eventBusManager.emit('onDownloadOptionsChanged', {\n items: null,\n zone: DASHBOARD_COMPONENT_NAME.HISTOGRAM,\n zoneLabel: t`Histogram`,\n });\n eventBusManager.removeEventListener('onDownloadOptionsRequested', emitDownloadOptions);\n };\n }, [completeCaseType, shouldShowGraph, canShowWidget, t]);\n\n const highlight = useCallback((caseIds: string[]) => {\n dashboardContext.highlight({\n caseIds,\n origin: DASHBOARD_COMPONENT_NAME.HISTOGRAM,\n });\n }, [dashboardContext]);\n\n const onEvents = useMemo<EChartsReactProps['onEvents']>(() => {\n\n const getCaseIdsFromPayload = (payload: unknown): string[] => {\n const colValues = HistogramUtil.getColValuesFromPayload(payload, conceptsA, conceptsB);\n if (!colValues) {\n return [];\n }\n const caseIds = sortedData.filter(caseDbCase => {\n const aValue = CaseUtil.getRowValue(caseDbCase.content, aCol, completeCaseType);\n const bValue = CaseUtil.getRowValue(caseDbCase.content, bCol, completeCaseType);\n return colValues.a === aValue.raw && colValues.b === bValue.raw;\n }).map(caseDbCase => caseDbCase.id);\n return caseIds;\n };\n\n return {\n globalout: () => {\n highlight([]);\n },\n mouseout: () => {\n highlight([]);\n },\n mouseover: (payload: unknown) => {\n highlight(getCaseIdsFromPayload(payload));\n },\n mouseup: (payload: unknown) => {\n const { event } = payload as { event: { event: MouseEvent } };\n setFocussedColValues(HistogramUtil.getColValuesFromPayload(payload, conceptsA, conceptsB));\n setContextMenuConfig({\n caseIds: getCaseIdsFromPayload(payload),\n mouseEvent: event.event,\n position: {\n left: (event.event).clientX,\n top: (event.event).clientY,\n },\n });\n },\n };\n }, [aCol, bCol, completeCaseType, conceptsA, conceptsB, highlight, sortedData]);\n\n const onShowOnlyFocussedColValuesMenuItemClick = useCallback(async (onMenuClose: () => void) => {\n if (!focussedColValues || !aCol || !bCol) {\n return;\n }\n await setFilterValues({\n [aCol.id]: [focussedColValues.a],\n [bCol.id]: [focussedColValues.b],\n });\n\n onMenuClose();\n }, [aCol, bCol, focussedColValues, setFilterValues]);\n\n const getEpiContextMenuExtraItems = useCallback((onMenuClose: () => void): ReactElement => {\n const conceptALabel = conceptsA.find(concept => concept.id === focussedColValues?.a)?.name;\n const conceptBLabel = conceptsB.find(concept => concept.id === focussedColValues?.b)?.name;\n if (!conceptALabel || !conceptBLabel) {\n return null;\n }\n if (!focussedColValues) {\n return null;\n }\n return (\n <MenuItem\n divider\n // eslint-disable-next-line @eslint-react/kit/jsx-no-bind\n onClick={async () => await onShowOnlyFocussedColValuesMenuItemClick(onMenuClose)}\n >\n <ListItemIcon>\n <FilterAltIcon fontSize={'small'} />\n </ListItemIcon>\n <ListItemText>\n {t('Filter (show only {{conceptALabel}} and {{conceptBLabel}})', { conceptALabel, conceptBLabel })}\n </ListItemText>\n </MenuItem>\n );\n }, [conceptsA, conceptsB, focussedColValues, onShowOnlyFocussedColValuesMenuItemClick, t]);\n\n useEffect(() => {\n const unsubscribe = dashboardContext.highlightSubject.subscribe((highlighting) => {\n if (highlighting.origin === DASHBOARD_COMPONENT_NAME.HISTOGRAM) {\n return;\n }\n const instance = chartInstanceRef.current;\n if (!instance) {\n return;\n }\n\n if (!highlighting?.caseIds?.length) {\n instance.dispatchAction({\n type: 'downplay',\n });\n return;\n }\n\n const highlightTargetsByDataIndex = new Map<number, Set<number>>();\n series?.forEach((serie, serieIndex) => {\n const castedSerie = serie as { data: unknown[]; xCaseIds: string[][] };\n castedSerie.xCaseIds?.forEach((caseIds: string[], dataIndex: number) => {\n if (intersection(caseIds, highlighting.caseIds).length) {\n const seriesIndices = highlightTargetsByDataIndex.get(dataIndex) ?? new Set<number>();\n seriesIndices.add(serieIndex);\n highlightTargetsByDataIndex.set(dataIndex, seriesIndices);\n }\n });\n });\n\n instance.dispatchAction({\n type: 'downplay',\n });\n\n const highlightBatch: Array<{ dataIndex: number; notBlur?: boolean; seriesIndex?: number }> = [];\n highlightTargetsByDataIndex.forEach((seriesIndices, dataIndex) => {\n if (seriesIndices.size === series?.length) {\n highlightBatch.push({\n dataIndex,\n });\n return;\n }\n\n seriesIndices.forEach((seriesIndex) => {\n highlightBatch.push({\n dataIndex,\n seriesIndex,\n });\n });\n });\n\n highlightBatch.forEach((target, index) => {\n if (index > 0) {\n target.notBlur = true;\n }\n });\n\n instance.dispatchAction({\n batch: highlightBatch,\n type: 'highlight',\n });\n });\n\n return () => {\n unsubscribe();\n };\n }, [dashboardContext, series]);\n\n return (\n <DashboardWidget\n expandDisabled={!canShowWidget}\n title={titleMenu}\n warningMessage={canShowWidget && histogramCaseCount > 0 && missingCasesCount > 0 ? t('Missing cases: {{missingCasesCount}} ({{missingCasesPercentage}}%)', { missingCasesCount, missingCasesPercentage }) : undefined}\n widgetName={DASHBOARD_COMPONENT_NAME.HISTOGRAM}\n >\n {!canShowWidget && (\n <WidgetUnavailable\n reason={widgetUnavailableReason}\n widgetLabel={t`histogram`}\n />\n )}\n {canShowWidget && (\n <Box\n sx={{\n height: '100%',\n position: 'relative',\n }}\n >\n {shouldShowGraph && (\n <EChartsReact\n echarts={echartsCore}\n notMerge\n onChartReady={onChartReady}\n onEvents={onEvents}\n option={getOptions()}\n opts={echartsOpts as unknown}\n ref={chartRef}\n style={{\n height: '100%',\n position: 'absolute',\n width: '100%',\n }}\n />\n )}\n <ContextMenu\n config={contextMenuConfig}\n getExtraItems={getEpiContextMenuExtraItems}\n onMenuClose={onEpiContextMenuClose}\n />\n </Box>\n )}\n </DashboardWidget>\n );\n};\n"],"mappings":"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"}
@@ -2,39 +2,39 @@ import { t as e } from "../../../_chunks/react.js";
2
2
  import { t } from "../../../_chunks/dashboardStore.js";
3
3
  import { EventBusService as n } from "../../../classes/services/EventBusService/index.js";
4
4
  import { t as r } from "../../../_chunks/shallow.js";
5
- import { n as i, o as a } from "../../../_chunks/index.esm.js";
6
- import { CaseDbColType as o } from "@gen-epix/api-casedb";
7
- import { StringUtil as s } from "@gen-epix/ui-core/utils/StringUtil";
8
- import { ConfigService as c } from "@gen-epix/ui-client-common/classes/services/ConfigService";
9
- import { Box as l } from "@mui/material";
10
- import { use as u, useCallback as d, useEffect as f, useMemo as p, useState as m } from "react";
11
- import { useTranslation as h } from "react-i18next";
12
- import { jsx as g } from "react/jsx-runtime";
13
- import { DownloadUtil as _ } from "@gen-epix/ui-core/utils/DownloadUtil";
5
+ import { CaseDbColType as i } from "@gen-epix/api-casedb";
6
+ import { StringUtil as a } from "@gen-epix/ui-core/utils/StringUtil";
7
+ import { ConfigService as o } from "@gen-epix/ui-client-common/classes/services/ConfigService";
8
+ import { Box as s } from "@mui/material";
9
+ import { use as c, useCallback as l, useEffect as u, useMemo as d, useState as f } from "react";
10
+ import { useTranslation as p } from "react-i18next";
11
+ import { jsx as m } from "react/jsx-runtime";
12
+ import { DownloadUtil as h } from "@gen-epix/ui-core/utils/DownloadUtil";
13
+ import { FormProvider as g, useForm as _ } from "react-hook-form";
14
14
  import { withDialog as v } from "@gen-epix/ui-core-components/hoc/withDialog";
15
15
  import { Autocomplete as y } from "@gen-epix/ui-core-form/components/fields/Autocomplete";
16
16
  import b from "@mui/icons-material/Download";
17
17
  import { AuthenticationService as x } from "@gen-epix/ui-client-common/classes/services/AuthenticationService";
18
18
  //#region src/components/ui/SequenceDownloadDialog/SequenceDownloadDialog.tsx
19
19
  var S = v(({ onActionsChange: v, onClose: S, onTitleChange: C, openProps: w }) => {
20
- let { t: T } = h(), E = u(t), D = e(E, r((e) => e.completeCaseType)), O = p(() => {
20
+ let { t: T } = p(), E = c(t), D = e(E, r((e) => e.completeCaseType)), O = d(() => {
21
21
  let e = [];
22
22
  return D.ordered_dim_ids.map((e) => D.dims[e]).forEach((t) => {
23
23
  D.ordered_col_ids_by_dim[t.id].map((e) => D.cols[e]).forEach((t) => {
24
- D.ref_cols[t.ref_col_id]?.col_type === o.GENETIC_SEQUENCE && e.push({
24
+ D.ref_cols[t.ref_col_id]?.col_type === i.GENETIC_SEQUENCE && e.push({
25
25
  label: t.label,
26
26
  value: t.id
27
27
  });
28
28
  });
29
29
  }), e;
30
- }, [D]), [k, A] = m(w?.geneticSequenceColId ?? O?.length === 1 ? O[0].value : ""), j = a({ values: { geneticSequenceColId: k } }), M = d(() => {}, []), N = d(() => {
31
- _.downloadAsMultiPartForm({
30
+ }, [D]), [k, A] = f(w?.geneticSequenceColId ?? O?.length === 1 ? O[0].value : ""), j = _({ values: { geneticSequenceColId: k } }), M = l(() => {}, []), N = l(() => {
31
+ h.downloadAsMultiPartForm({
32
32
  accessToken: x.getInstance().authContextProps?.user?.access_token ?? "",
33
- action: `${c.getInstance().config.getAPIBaseUrl()}/v1/retrieve/genetic_sequence/fasta`,
33
+ action: `${o.getInstance().config.getAPIBaseUrl()}/v1/retrieve/genetic_sequence/fasta`,
34
34
  data: {
35
35
  case_ids: w.cases.map((e) => e.id),
36
36
  case_type_id: D.id,
37
- file_name: `${s.createSlug(D.name)}-${s.createSlug(O.find((e) => e.value === k)?.label)}-sequences.fasta`,
37
+ file_name: `${a.createSlug(D.name)}-${a.createSlug(O.find((e) => e.value === k)?.label)}-sequences.fasta`,
38
38
  genetic_sequence_col_id: k
39
39
  }
40
40
  }), S();
@@ -46,14 +46,14 @@ var S = v(({ onActionsChange: v, onClose: S, onTitleChange: C, openProps: w }) =
46
46
  S,
47
47
  w.cases
48
48
  ]);
49
- return f(() => {
49
+ return u(() => {
50
50
  C(T`Download sequences`);
51
- }, [C, T]), f(() => {
51
+ }, [C, T]), u(() => {
52
52
  let e = [{
53
53
  disabled: !k,
54
54
  label: T`Download FASTA`,
55
55
  onClick: N,
56
- startIcon: /* @__PURE__ */ g(b, {})
56
+ startIcon: /* @__PURE__ */ m(b, {})
57
57
  }];
58
58
  v(e);
59
59
  let t = (t) => {
@@ -73,14 +73,14 @@ var S = v(({ onActionsChange: v, onClose: S, onTitleChange: C, openProps: w }) =
73
73
  N,
74
74
  w.cases,
75
75
  T
76
- ]), /* @__PURE__ */ g(l, { children: /* @__PURE__ */ g(l, {
76
+ ]), /* @__PURE__ */ m(s, { children: /* @__PURE__ */ m(s, {
77
77
  sx: { marginBottom: 3 },
78
- children: /* @__PURE__ */ g(i, {
78
+ children: /* @__PURE__ */ m(g, {
79
79
  ...j,
80
- children: /* @__PURE__ */ g("form", {
80
+ children: /* @__PURE__ */ m("form", {
81
81
  autoComplete: "off",
82
82
  onSubmit: M,
83
- children: /* @__PURE__ */ g(y, {
83
+ children: /* @__PURE__ */ m(y, {
84
84
  disabled: O.length < 2,
85
85
  label: T`Genetic sequence column`,
86
86
  name: "geneticSequenceColId",
@@ -46,7 +46,9 @@
46
46
  "Add {{numCases}} selected case(s) to an existing event": "Add {{numCases}} selected case(s) to an existing event",
47
47
  "Add a widget": "Add a widget",
48
48
  "Add case": "Add case",
49
+ "Add case must be enabled for private policies": "Add case must be enabled for private policies",
49
50
  "Add case set": "Add case set",
51
+ "Add case set must be enabled for private policies": "Add case set must be enabled for private policies",
50
52
  "Add case set: {{addCaseSet}}": "Add case set: {{addCaseSet}}",
51
53
  "Add case: {{addCase}}": "Add case: {{addCase}}",
52
54
  "Add selected cases to an existing event": "Add selected cases to an existing event",
@@ -437,6 +439,7 @@
437
439
  "Read case set": "Read case set",
438
440
  "Read case set: {{readCaseSet}}": "Read case set: {{readCaseSet}}",
439
441
  "Read column set": "Read column set",
442
+ "Read column set is required for private policies": "Read column set is required for private policies",
440
443
  "Read column sets": "Read column sets",
441
444
  "Read max number of cases": "Read max number of cases",
442
445
  "Read max tree size": "Read max tree size",
@@ -467,7 +470,9 @@
467
470
  "Remove": "Remove",
468
471
  "Remove all similar cases from result": "Remove all similar cases from result",
469
472
  "Remove case": "Remove case",
473
+ "Remove case must be enabled for private policies": "Remove case must be enabled for private policies",
470
474
  "Remove case set": "Remove case set",
475
+ "Remove case set must be enabled for private policies": "Remove case set must be enabled for private policies",
471
476
  "Remove case set: {{removeCaseSet}}": "Remove case set: {{removeCaseSet}}",
472
477
  "Remove case: {{removeCase}}": "Remove case: {{removeCase}}",
473
478
  "Remove from selected rows": "Remove from selected rows",
@@ -651,6 +656,7 @@
651
656
  "Write case set": "Write case set",
652
657
  "Write case set: {{writeCaseSet}}": "Write case set: {{writeCaseSet}}",
653
658
  "Write column set": "Write column set",
659
+ "Write column set is required for private policies": "Write column set is required for private policies",
654
660
  "Write column sets": "Write column sets",
655
661
  "X-Axis: {{label}}": "X-Axis: {{label}}",
656
662
  "Yes": "Yes",
@@ -46,7 +46,9 @@
46
46
  "Add {{numCases}} selected case(s) to an existing event": "Voeg {{numCases}} geselecteerde casus(sen) toe aan een bestaande event",
47
47
  "Add a widget": "Widget toevoegen",
48
48
  "Add case": "Casus toevoegen",
49
+ "Add case must be enabled for private policies": "Casus toevoegen moet zijn ingeschakeld voor privébeleidsregels",
49
50
  "Add case set": "Casus set toevoegen",
51
+ "Add case set must be enabled for private policies": "Casus set toevoegen moet zijn ingeschakeld voor privébeleidsregels",
50
52
  "Add case set: {{addCaseSet}}": "Voeg casus set toe: {{addCaseSet}}",
51
53
  "Add case: {{addCase}}": "Voeg casus toe: {{addCase}}",
52
54
  "Add selected cases to an existing event": "Geselecteerde casussen toevoegen aan een bestaande event",
@@ -437,6 +439,7 @@
437
439
  "Read case set": "Lees casus set",
438
440
  "Read case set: {{readCaseSet}}": "Lees casus set: {{readCaseSet}}",
439
441
  "Read column set": "Lees kolom set",
442
+ "Read column set is required for private policies": "Lees kolom set is verplicht voor privébeleidsregels",
440
443
  "Read column sets": "Lees kolom sets",
441
444
  "Read max number of cases": "Lees max aantal casussen",
442
445
  "Read max tree size": "Lees max boom grootte",
@@ -467,7 +470,9 @@
467
470
  "Remove": "Verwijderen",
468
471
  "Remove all similar cases from result": "Alle vergelijkbare casussen uit resultaat verwijderen",
469
472
  "Remove case": "Casus verwijderen",
473
+ "Remove case must be enabled for private policies": "Casus verwijderen moet zijn ingeschakeld voor privébeleidsregels",
470
474
  "Remove case set": "Casus set verwijderen",
475
+ "Remove case set must be enabled for private policies": "Casus set verwijderen moet zijn ingeschakeld voor privébeleidsregels",
471
476
  "Remove case set: {{removeCaseSet}}": "Verwijder casus set: {{removeCaseSet}}",
472
477
  "Remove case: {{removeCase}}": "Verwijder casus: {{removeCase}}",
473
478
  "Remove from selected rows": "Verwijderen uit geselecteerde rijen",
@@ -651,6 +656,7 @@
651
656
  "Write case set": "Schrijf casus set",
652
657
  "Write case set: {{writeCaseSet}}": "Schrijf casus set: {{writeCaseSet}}",
653
658
  "Write column set": "Schrijf kolom set",
659
+ "Write column set is required for private policies": "Schrijf kolom set is verplicht voor privébeleidsregels",
654
660
  "Write column sets": "Schrijf kolom sets",
655
661
  "X-Axis: {{label}}": "X-as: {{label}}",
656
662
  "Yes": "Ja",
@@ -662,4 +668,4 @@
662
668
  "You do not have the required permissions to create an event. Contact your organization administrator for assistance.": "U heeft niet de vereiste rechten om een event aan te maken. Neem contact op met uw organisatiebeheerder voor hulp.",
663
669
  "You have exceeded the maximum number of {{maxCases}} cases for this case type. Please reduce the number of selected cases before proceeding.": "U heeft het maximale aantal van {{maxCases}} casussen voor dit casus type overschreden. Verminder het aantal geselecteerde casussen voordat u doorgaat."
664
670
  }
665
- }
671
+ }
@@ -1,6 +1,6 @@
1
1
  import { CASEDB_QUERY_KEY as e } from "../../constants/query.js";
2
2
  import { n as t } from "../../_chunks/Dashboard.js";
3
- import { t as n } from "../../_chunks/chunk-BV7QT456.js";
3
+ import { t as n } from "../../_chunks/chunk-OB3PAWPO.js";
4
4
  import { CaseDbCaseApi as r } from "@gen-epix/api-casedb";
5
5
  import { useEffect as i, useMemo as a } from "react";
6
6
  import { useTranslation as o } from "react-i18next";
@@ -3,7 +3,7 @@ import { CaseDbDataUtil as t } from "../../utils/CaseDbDataUtil/index.js";
3
3
  import { useCaseTypeMapQuery as n, useCaseTypeOptionsQuery as r } from "../../dataHooks/useCaseTypesQuery/index.js";
4
4
  import { useDimMapQuery as i, useDimOptionsQuery as a } from "../../dataHooks/useDimsQuery/index.js";
5
5
  import { useColMapQuery as o, useColOptionsQuery as s } from "../../dataHooks/useColsQuery/index.js";
6
- import { t as ee } from "../../_chunks/chunk-BV7QT456.js";
6
+ import { t as ee } from "../../_chunks/chunk-OB3PAWPO.js";
7
7
  import { useRefColMapQuery as c, useRefColOptionsQuery as l } from "../../dataHooks/useRefColsQuery/index.js";
8
8
  import { useTreeAlgorithmCodeOptionsQuery as u } from "../../dataHooks/useTreeAlgorithmCodesQuery/index.js";
9
9
  import { useRefColsValidationRulesQuery as d } from "../../dataHooks/useRefColsValidationRulesQuery/index.js";
@@ -1,5 +1,5 @@
1
1
  import { CASEDB_QUERY_KEY as e } from "../../constants/query.js";
2
- import { t } from "../../_chunks/chunk-BV7QT456.js";
2
+ import { t } from "../../_chunks/chunk-OB3PAWPO.js";
3
3
  import { object as n } from "yup";
4
4
  import { CaseDbCommandName as r, CaseDbOntologyApi as i } from "@gen-epix/api-casedb";
5
5
  import { FORM_FIELD_DEFINITION_TYPE as a } from "@gen-epix/ui-core-form/models/form";
@@ -1,6 +1,6 @@
1
1
  import { CASEDB_QUERY_KEY as e } from "../../constants/query.js";
2
2
  import { useCaseTypeMapQuery as t, useCaseTypeOptionsQuery as n } from "../../dataHooks/useCaseTypesQuery/index.js";
3
- import { t as r } from "../../_chunks/chunk-BV7QT456.js";
3
+ import { t as r } from "../../_chunks/chunk-OB3PAWPO.js";
4
4
  import { useRefDimOptionsQuery as i } from "../../dataHooks/useRefDimsQuery/index.js";
5
5
  import { boolean as a, object as o, string as s } from "yup";
6
6
  import { CaseDbCaseApi as c, CaseDbCommandName as l, CaseDbPermissionType as u } from "@gen-epix/api-casedb";
@@ -1,7 +1,7 @@
1
1
  import { CASEDB_QUERY_KEY as e } from "../../constants/query.js";
2
2
  import { useCaseTypeMapQuery as t } from "../../dataHooks/useCaseTypesQuery/index.js";
3
3
  import { n } from "../../_chunks/Dashboard.js";
4
- import { t as r } from "../../_chunks/chunk-BV7QT456.js";
4
+ import { t as r } from "../../_chunks/chunk-OB3PAWPO.js";
5
5
  import { CaseDbCaseApi as i } from "@gen-epix/api-casedb";
6
6
  import { useEffect as a, useMemo as o } from "react";
7
7
  import { useTranslation as s } from "react-i18next";
@@ -26,96 +26,129 @@ var b = () => {
26
26
  id: t.id,
27
27
  ...e
28
28
  })).data, []), A = d(async (e) => (await c.getInstance().organizationAccessCasePoliciesPostOne(e)).data, []), j = d((e) => T.getName(e), [T]), M = f(() => o().shape({
29
- add_case: a().required(),
30
- add_case_set: a().required(),
29
+ add_case: a().when("is_private", {
30
+ is: !0,
31
+ otherwise: () => a().required(),
32
+ then: () => a().required().oneOf([!0], b`Add case must be enabled for private policies`)
33
+ }),
34
+ add_case_set: a().when("is_private", {
35
+ is: !0,
36
+ otherwise: () => a().required(),
37
+ then: () => a().required().oneOf([!0], b`Add case set must be enabled for private policies`)
38
+ }),
31
39
  case_type_set_id: s().uuid4().required().max(100),
32
40
  data_collection_id: s().uuid4().required().max(100),
33
41
  is_active: a().required(),
34
42
  is_private: a().required(),
35
43
  organization_id: s().uuid4().required().max(100),
36
44
  read_case_set: a().required(),
37
- read_col_set_id: s().uuid4().required().max(100),
38
- remove_case: a().required(),
39
- remove_case_set: a().required(),
45
+ read_col_set_id: s().when("is_private", {
46
+ is: !0,
47
+ otherwise: () => s().nullable().notRequired().max(100),
48
+ then: () => s().uuid4().required(b`Read column set is required for private policies`).max(100)
49
+ }),
50
+ remove_case: a().when("is_private", {
51
+ is: !0,
52
+ otherwise: () => a().required(),
53
+ then: () => a().required().oneOf([!0], b`Remove case must be enabled for private policies`)
54
+ }),
55
+ remove_case_set: a().when("is_private", {
56
+ is: !0,
57
+ otherwise: () => a().required(),
58
+ then: () => a().required().oneOf([!0], b`Remove case set must be enabled for private policies`)
59
+ }),
40
60
  write_case_set: a().required(),
41
- write_col_set_id: s().uuid4().nullable().notRequired().max(100)
42
- }), []), N = f(() => [
43
- {
44
- definition: u.AUTOCOMPLETE,
45
- label: b`Organization`,
46
- loading: x.isLoading,
47
- name: "organization_id",
48
- options: x.options
49
- },
50
- {
51
- definition: u.AUTOCOMPLETE,
52
- label: b`Data collection`,
53
- loading: S.isLoading,
54
- name: "data_collection_id",
55
- options: S.options
56
- },
57
- {
58
- definition: u.AUTOCOMPLETE,
59
- label: b`Case type set`,
60
- loading: w.isLoading,
61
- name: "case_type_set_id",
62
- options: w.options
63
- },
64
- {
65
- definition: u.AUTOCOMPLETE,
66
- label: b`Read column set`,
67
- loading: C.isLoading,
68
- name: "read_col_set_id",
69
- options: C.options
70
- },
71
- {
72
- definition: u.AUTOCOMPLETE,
73
- label: b`Write column set`,
74
- loading: C.isLoading,
75
- name: "write_col_set_id",
76
- options: C.options
77
- },
78
- {
79
- definition: u.BOOLEAN,
80
- label: b`Add case`,
81
- name: "add_case"
82
- },
83
- {
84
- definition: u.BOOLEAN,
85
- label: b`Remove case`,
86
- name: "remove_case"
87
- },
88
- {
89
- definition: u.BOOLEAN,
90
- label: b`Add case set`,
91
- name: "add_case_set"
92
- },
93
- {
94
- definition: u.BOOLEAN,
95
- label: b`Remove case set`,
96
- name: "remove_case_set"
97
- },
98
- {
99
- definition: u.BOOLEAN,
100
- label: b`Read case set`,
101
- name: "read_case_set"
102
- },
103
- {
104
- definition: u.BOOLEAN,
105
- label: b`Write case set`,
106
- name: "write_case_set"
107
- },
108
- {
109
- definition: u.BOOLEAN,
110
- label: b`Is private`,
111
- name: "is_private"
112
- },
113
- {
114
- definition: u.BOOLEAN,
115
- label: b`Is active`,
116
- name: "is_active"
117
- }
118
- ], [
61
+ write_col_set_id: s().when("is_private", {
62
+ is: !0,
63
+ otherwise: () => s().nullable().notRequired().max(100),
64
+ then: () => s().uuid4().required(b`Write column set is required for private policies`).max(100)
65
+ })
66
+ }), [b]), N = d((e, t, n) => {
67
+ t?.is_private === !0 && t?.add_case !== !0 && n.setValue("add_case", !0), t?.is_private === !0 && t?.add_case_set !== !0 && n.setValue("add_case_set", !0), t?.is_private === !0 && t?.remove_case !== !0 && n.setValue("remove_case", !0), t?.is_private === !0 && t?.remove_case_set !== !0 && n.setValue("remove_case_set", !0);
68
+ }, []), P = d((e, t) => {
69
+ let n = t?.is_private ?? e?.is_private ?? !1;
70
+ return [
71
+ {
72
+ definition: u.AUTOCOMPLETE,
73
+ label: b`Organization`,
74
+ loading: x.isLoading,
75
+ name: "organization_id",
76
+ options: x.options
77
+ },
78
+ {
79
+ definition: u.AUTOCOMPLETE,
80
+ label: b`Data collection`,
81
+ loading: S.isLoading,
82
+ name: "data_collection_id",
83
+ options: S.options
84
+ },
85
+ {
86
+ definition: u.AUTOCOMPLETE,
87
+ label: b`Case type set`,
88
+ loading: w.isLoading,
89
+ name: "case_type_set_id",
90
+ options: w.options
91
+ },
92
+ {
93
+ definition: u.AUTOCOMPLETE,
94
+ label: b`Read column set`,
95
+ loading: C.isLoading,
96
+ name: "read_col_set_id",
97
+ options: C.options
98
+ },
99
+ {
100
+ definition: u.AUTOCOMPLETE,
101
+ label: b`Write column set`,
102
+ loading: C.isLoading,
103
+ name: "write_col_set_id",
104
+ options: C.options
105
+ },
106
+ {
107
+ definition: u.BOOLEAN,
108
+ disabled: n,
109
+ label: b`Add case`,
110
+ name: "add_case"
111
+ },
112
+ {
113
+ definition: u.BOOLEAN,
114
+ disabled: n,
115
+ label: b`Remove case`,
116
+ name: "remove_case"
117
+ },
118
+ {
119
+ definition: u.BOOLEAN,
120
+ disabled: n,
121
+ label: b`Add case set`,
122
+ name: "add_case_set"
123
+ },
124
+ {
125
+ definition: u.BOOLEAN,
126
+ disabled: n,
127
+ label: b`Remove case set`,
128
+ name: "remove_case_set"
129
+ },
130
+ {
131
+ definition: u.BOOLEAN,
132
+ label: b`Read case set`,
133
+ name: "read_case_set"
134
+ },
135
+ {
136
+ definition: u.BOOLEAN,
137
+ label: b`Write case set`,
138
+ name: "write_case_set"
139
+ },
140
+ {
141
+ definition: u.BOOLEAN,
142
+ label: b`Is private`,
143
+ name: "is_private"
144
+ },
145
+ {
146
+ definition: u.BOOLEAN,
147
+ label: b`Is active`,
148
+ name: "is_active"
149
+ }
150
+ ];
151
+ }, [
119
152
  C.isLoading,
120
153
  C.options,
121
154
  w.isLoading,
@@ -125,7 +158,7 @@ var b = () => {
125
158
  x.isLoading,
126
159
  x.options,
127
160
  b
128
- ]), P = f(() => [
161
+ ]), F = f(() => [
129
162
  g.createOptionsColumn({
130
163
  id: "organization_id",
131
164
  name: b`Organization`,
@@ -198,13 +231,14 @@ var b = () => {
198
231
  defaultSortDirection: "asc",
199
232
  deleteOne: O,
200
233
  fetchAll: D,
201
- formFieldDefinitions: N,
234
+ formFieldDefinitions: P,
202
235
  getName: j,
203
236
  itemName: b`Organization access case policy`,
204
237
  loadables: E,
238
+ onFormChange: N,
205
239
  resourceQueryKeyBase: e.ORGANIZATION_ACCESS_CASE_POLICIES,
206
240
  schema: M,
207
- tableColumns: P,
241
+ tableColumns: F,
208
242
  testIdAttributes: _.createAttributes("OrganizationAccessCasePoliciesAdminPage"),
209
243
  title: b`Organization access case policies`,
210
244
  updateOne: k