diff --git a/v3/cypress/e2e/case-card.spec.ts b/v3/cypress/e2e/case-card.spec.ts index 64230f87b2..e5bd8c35fc 100644 --- a/v3/cypress/e2e/case-card.spec.ts +++ b/v3/cypress/e2e/case-card.spec.ts @@ -132,7 +132,7 @@ context("case card", () => { cy.get('[data-testid="case-card-view-next-button"]').should("have.length", 2).and("not.be.disabled") cy.get('[data-testid="case-card-view-index"]').should("have.length", 2) cy.get('[data-testid="case-card-view-index"]').eq(0).should("have.text", "12 cases") - cy.get('[data-testid="case-card-view-index"]').eq(1).should("have.text", "2 cases") + cy.get('[data-testid="case-card-view-index"]').eq(1).should("have.text", "27 cases") cy.get('[data-testid="case-card-attrs"]').should("have.length", 2) cy.get('[data-testid="case-card-attrs"]').eq(0).find('[data-testid="case-card-attr"]').should("have.length", 1) cy.get('[data-testid="case-card-attrs"]').eq(0).find('[data-testid="case-card-attr-name"]') @@ -243,6 +243,7 @@ context("case card", () => { table.toggleCaseView() cy.wait(500) cy.get('[data-testid="case-card-view"]').should("have.length", 3) + cy.get('[data-testid="case-card-view-next-button"]').eq(0).click() cy.log("Add new case to 'middle' collection.") cy.get('[data-testid="case-card-view"]').eq(1).find('[data-testid="case-card-view-index"]') .eq(0).should("have.text", "4 cases") @@ -267,7 +268,7 @@ context("case card", () => { // Check for undo/redo after adding a new case toolbar.getUndoTool().click() cy.get('[data-testid="case-card-view"]').eq(1).find('[data-testid="case-card-view-index"]') - .eq(0).should("have.text", "4 cases") + .eq(0).should("have.text", "14 cases") /* Note that selection is not guaranteed to be restored on undo/redo. @@ -285,6 +286,36 @@ context("case card", () => { .eq(0).should("contain.text", "New Order") */ }) + it("adds a new case with the correct parent values depending on what is selected", () => { + table.moveAttributeToParent("Order", "newCollection") + cy.wait(500) + table.moveAttributeToParent("Diet", "newCollection") + cy.wait(500) + table.toggleCaseView() + cy.wait(500) + cy.get('[data-testid="case-card-view"]').should("have.length", 3) + + // when no cases are selected, should always add a case to the root level + cy.get('[data-testid="case-card-view"]').eq(0).find('[data-testid="case-card-view-index"]') + .eq(0).should("have.text", "3 cases") + cy.get('[data-testid="case-card-view"]').eq(2).find('[data-testid="add-case-button"]') + .eq(0).click() + cy.get('[data-testid="case-card-view"]').eq(0).find('[data-testid="case-card-view-index"]') + .eq(0).should("have.text", "4 of 4") + + // toolbar.getUndoTool().click() + // cy.get('[data-testid="case-card-view-next-button"]').eq(0).click() + // cy.get('[data-testid="case-card-view"]').eq(1).find('[data-testid="case-card-view-index"]') + // .eq(0).should("have.text", "4 cases") + // cy.get('[data-testid="case-card-view"]').eq(1).find('[data-testid="add-case-button"]') + // .eq(0).click() + // cy.get('[data-testid="case-card-view"]').eq(1).find('[data-testid="case-card-view-index"]') + // .eq(0).should("have.text", "5 of 5") + // cy.get('[data-testid="case-card-view"]').eq(0).find('[data-testid="case-card-attr-value-text-editor"]') + // .eq(0).should("have.text", "plants") + // cy.get('[data-testid="case-card-view"]').eq(1).find('[data-testid="case-card-attr-value-text-editor"]') + // .eq(0).should("have.text", "") + }) it("allows a user to drag an attribute to a new collection", () => { table.toggleCaseView() cy.wait(500) @@ -348,16 +379,16 @@ context("case card inspector panel", () => { cy.wait(500) cy.get('[data-testid="trash-menu-list"]').should("be.visible") card.getDeleteSelectedCasesButton().click() + cy.get('[data-testid="case-card-view-index"]').should("have.text", "26 cases") + cy.get('[data-testid="case-card-attr-value"]').first().should("have.text", "26 values") + cy.get('[data-testid="case-card-view-next-button"]').click() cy.get('[data-testid="case-card-view-index"]').should("have.text", "1 of 26") cy.get('[data-testid="case-card-attr-value"]').first().should("have.text", "Asian Elephant") - cy.get('[data-testid="case-card-view-next-button"]').click() - cy.get('[data-testid="case-card-view-index"]').should("have.text", "2 of 26") - cy.get('[data-testid="case-card-attr-value"]').first().should("have.text", "Big Brown Bat") card.getDeleteCasesButton().click() cy.wait(500) card.getDeleteUnselectedCasesButton().click() cy.get('[data-testid="case-card-view-index"]').should("have.text", "1 of 1") - cy.get('[data-testid="case-card-attr-value"]').first().should("have.text", "Big Brown Bat") + cy.get('[data-testid="case-card-attr-value"]').first().should("have.text", "Asian Elephant") }) it("allows user to set aside and restore cases from inspector panel", () => { table.toggleCaseView() @@ -373,8 +404,8 @@ context("case card inspector panel", () => { card.getRestoreSetAsideCasesButton().should("be.disabled").and("have.text", "Restore 0 Set Aside Cases") // resorting to {force: true} because this is failing in CI, though it passes locally card.getSetAsideSelectedCasesButton().click({force: true}) - cy.get('[data-testid="case-card-view-index"]').should("have.text", "1 of 26") - cy.get('[data-testid="case-card-attr-value"]').first().should("have.text", "Asian Elephant") + cy.get('[data-testid="case-card-view-index"]').should("have.text", "26 cases") + cy.get('[data-testid="case-card-attr-value"]').first().should("have.text", "26 values") card.getHideShowButton().click() cy.wait(500) card.getRestoreSetAsideCasesButton().should("not.be.disabled").and("have.text", "Restore 1 Set Aside Cases") @@ -397,7 +428,6 @@ context("case card inspector panel", () => { card.getHideShowButton().click() cy.wait(500) card.getShowAllHiddenAttributesButton().should("be.disabled") - // FIXME: Reinstate the below after figuring out why clicking attribute buttons does nothing in Cypress cy.get('[data-testid="case-card-attr-name"]').eq(8).click() cy.get('[data-testid="attribute-menu-list"]').should("be.visible") cy.get('[data-testid="attribute-menu-list"]').find("button").contains("Hide Attribute").click() diff --git a/v3/src/components/case-card/card-view.scss b/v3/src/components/case-card/card-view.scss index 17f0ff55e2..a6040c935f 100644 --- a/v3/src/components/case-card/card-view.scss +++ b/v3/src/components/case-card/card-view.scss @@ -30,7 +30,7 @@ color: #0592af; cursor: pointer; display: block; - font-size: 10px; + font-size: 11px; font-weight: bold; margin: 0 auto; padding: 6px 8px; diff --git a/v3/src/components/case-card/card-view.tsx b/v3/src/components/case-card/card-view.tsx index 4ab4bf22c4..9c1a71d554 100644 --- a/v3/src/components/case-card/card-view.tsx +++ b/v3/src/components/case-card/card-view.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useRef } from "react" +import React, { useRef } from "react" import { observer } from "mobx-react-lite" -import { mstReaction } from "../../utilities/mst-reaction" import { CollectionContext } from "../../hooks/use-collection-context" import { AttributeHeaderDividerContext } from "../case-tile-common/use-attribute-header-divider-context" import { CaseView } from "./case-view" @@ -18,40 +17,30 @@ export const CardView = observer(function CardView({onNewCollectionDrop}: CardVi const cardModel = useCaseCardModel() const data = cardModel?.data const collections = data?.collections - const areAllCollectionsSummarized = !!collections?.every(c => cardModel?.summarizedCollections.includes(c.id)) const rootCollection = collections?.[0] const selectedItems = data?.selection const selectedItemId = selectedItems && Array.from(selectedItems)[0] const selectedItemLineage = cardModel?.caseLineage(selectedItemId) const contentRef = useRef(null) + const summarizedCollections = cardModel?.summarizedCollections || [] + const isInSummaryMode = summarizedCollections.length > 0 - const handleSelectCases = (caseIds: string[], collectionId: string) => { - cardModel?.setShowSummary(caseIds.length > 1, collectionId) + const handleSelectCases = (caseIds: string[]) => { data?.setSelectedCases(caseIds) } const handleSummaryButtonClick = () => { - cardModel?.setShowSummary(!areAllCollectionsSummarized) - } - - // The first time the card is rendered, summarize all collections unless there is a selection. - useEffect(function startWithAllCollectionsSummarized() { - if (data?.selection.size === 0) { - cardModel?.summarizeAllCollections() + if (isInSummaryMode) { + // select the first child-most case + const firstItemId = data?.itemIds[0] + const firstItemLineage = cardModel?.caseLineage(firstItemId) + if (firstItemLineage) { + data?.setSelectedCases([firstItemLineage[firstItemLineage.length - 1]]) + } + } else { + data?.setSelectedCases([]) } - }, [cardModel, data]) - - // When all cases are selected, show summary. - useEffect(function showSummaryOnAllCasesSelection() { - return mstReaction( - () => selectedItems?.size, - () => { - if (selectedItems?.size === data?.items.length) { - cardModel?.summarizeAllCollections() - } - }, {name: "CardView.showSummaryOnAllCasesSelection"}, data - ) - }, [cardModel, data, selectedItems]) + } return (
@@ -72,7 +61,7 @@ export const CardView = observer(function CardView({onNewCollectionDrop}: CardVi onClick={handleSummaryButtonClick} disabled={data?.items.length === 0} > - { areAllCollectionsSummarized + { isInSummaryMode ? t("V3.caseCard.summaryButton.showIndividualCases") : t("V3.caseCard.summaryButton.showSummary") } diff --git a/v3/src/components/case-card/case-attrs-view.tsx b/v3/src/components/case-card/case-attrs-view.tsx index 2b379b4e1c..34045d312d 100644 --- a/v3/src/components/case-card/case-attrs-view.tsx +++ b/v3/src/components/case-card/case-attrs-view.tsx @@ -35,10 +35,10 @@ export const CaseAttrsView = observer(function CaseAttrsView({caseItem, collecti !!cardModel?.summarizedCollections.find(cid => cid === collection?.id) const contentRef = useRef(null) const [, setCellElt] = useState(null) + const summaryValues = displayValues && collection ? displayValues(collection, caseItem) : [] const values: IValueType[] = collection?.attributes.map(attr => { return attr?.id && data?.getValue(caseItem?.__id__, attr.id) }) ?? [] - const summaryValues = displayValues && collection ? displayValues(collection, caseItem) : [] const handleSetHeaderContentElt = useCallback((contentElt: HTMLDivElement | null) => { contentRef.current = contentElt @@ -68,7 +68,7 @@ export const CaseAttrsView = observer(function CaseAttrsView({caseItem, collecti if (!attr || metadata?.isHidden(attr.id)) return null return ( { + if (cases.length === 1) return 0 + let displayedCaseIndex = cases.findIndex(c => data?.isCaseSelected(c.__id__)) + if (displayedCaseIndex === -1) { + // the child case is selected and not the parent, so we need to find the case that has the selected child + const selectedItemId = data?.selection && Array.from(data.selection)[0] + const selectedCaseId = cardModel?.caseLineage(selectedItemId)?.[level] + const selectedCase = collection?.cases.find(c => c.__id__ === selectedCaseId) + displayedCaseIndex = cases.findIndex(c => c.__id__ === selectedCase?.__id__) + } + return displayedCaseIndex + } + + const getCaseIndexText = () => { + if (isCollectionSummarized) { + let summaryTotal = 0 + if (data?.selection.size === 0) { + summaryTotal = collection?.cases.length ?? 0 + } else if (!collection?.child) { + summaryTotal = collection?.cases.filter(c => data?.isCaseSelected(c.__id__)).length ?? 0 + } else { + const anyChildSelectedCount = collection?.cases.reduce((count, { __id__ }) => { + const caseInfo = data?.caseInfoMap.get(__id__) + return caseInfo?.childItemIds.some(id => data?.selection?.has(id)) ? count + 1 : count + }, 0) + summaryTotal = anyChildSelectedCount + } + + return `${summaryTotal} ${summaryTotal === 1 + ? t("DG.DataContext.singleCaseName") + : t("DG.DataContext.pluralCaseName")}` + } else { + return `${getDisplayedCaseIndex() + 1} of ${cases.length}` + } + } + + const handleSelectCase = (delta: number) => { + const displayedCaseIndex = getDisplayedCaseIndex() + const selectedCaseIndex = isCollectionSummarized + ? delta < 0 ? cases.length - 1 : 0 + : displayedCaseIndex + delta + const newCase = cases[selectedCaseIndex] + if (!newCase.__id__) return + data?.setSelectedCases([newCase.__id__]) + } + + const handleAddNewCase = () => { + if (collection) { + let newCaseId: string | undefined + data?.applyModelChange(() => { + const newItemId = cardModel?.addNewCase() + newCaseId = newItemId && data?.getItemCaseIds(newItemId)[level] + newCaseId && data?.setSelectedCases([newCaseId]) + }, { + notify: () => { + if (newCaseId) { + return createCasesNotification([newCaseId], data) + } + }, + undoStringKey: "DG.Undo.caseTable.createNewCase", + redoStringKey: "DG.Redo.caseTable.createNewCase" + }) + } + } + + const prevButtonDisabled = isCollectionSummarized || (!isCollectionSummarized && getDisplayedCaseIndex() === 0) + const nextButtonDisabled = !isCollectionSummarized && getDisplayedCaseIndex() === cases.length - 1 + + return ( +
+
+ +
+
+ + + {getCaseIndexText()} + + +
+
+ +
+
+ ) +}) diff --git a/v3/src/components/case-card/case-card-model.ts b/v3/src/components/case-card/case-card-model.ts index 744aa0f459..00f05468ec 100644 --- a/v3/src/components/case-card/case-card-model.ts +++ b/v3/src/components/case-card/case-card-model.ts @@ -1,6 +1,5 @@ import { Instance, SnapshotIn, types } from "mobx-state-tree" import { getTileCaseMetadata, getTileDataSet } from "../../models/shared/shared-data-utils" -import { ISharedModel } from "../../models/shared/shared-model" import { ITileContentModel, TileContentModel } from "../../models/tiles/tile-content" import { kCaseCardTileType } from "./case-card-defs" import { ICollectionModel } from "../../models/data/collection" @@ -13,7 +12,6 @@ export const CaseCardModel = TileContentModel type: types.optional(types.literal(kCaseCardTileType), kCaseCardTileType), // key is collection id; value is width attributeColumnWidths: types.map(types.number), - summarizedCollections: types.optional(types.array(types.string), []) }) .views(self => ({ get data() { @@ -26,6 +24,37 @@ export const CaseCardModel = TileContentModel return self.attributeColumnWidths.get(collectionId) } })) + .views(self => ({ + get summarizedCollections() { + const selectedItems = self.data?.selection + const items = self.data?.items + const collections = self.data?.collections + + if (!collections || !items || selectedItems?.size === 1) { + return [] + } + + const collectionIdsToSummarize: string[] = [] + + collections.forEach((collection, index) => { + if (index < collections.length - 1) { + const cases = self.data?.getCasesForCollection(collection.id) ?? [] + const anyChildSelectedCount = cases.reduce((count, { __id__ }) => { + const caseInfo = self.data?.caseInfoMap.get(__id__) + return caseInfo?.childItemIds.some(id => selectedItems?.has(id)) ? count + 1 : count + }, 0) + if (cases.length > 1 && anyChildSelectedCount !== 1) { + collectionIdsToSummarize.push(collection.id) + } + } else { + // always summarize the last collection + collectionIdsToSummarize.push(collection.id) + } + }) + + return collectionIdsToSummarize + } + })) .views(self => ({ caseLineage(itemId?: string) { if (!itemId) return undefined @@ -35,8 +64,8 @@ export const CaseCardModel = TileContentModel const parentCaseInfo = self.data?.caseInfoMap.get(parentCaseId) if (!parentCaseInfo?.childCaseIds) return undefined return parentCaseInfo.childCaseIds - .map(childCaseId => self.data?.caseInfoMap.get(childCaseId)?.groupedCase) - .filter(groupedCase => !!groupedCase) + .map(childCaseId => self.data?.caseInfoMap.get(childCaseId)?.groupedCase) + .filter(groupedCase => !!groupedCase) }, displayValues(collection: ICollectionModel, caseItem: IGroupedCase) { @@ -44,10 +73,10 @@ export const CaseCardModel = TileContentModel const minValue = Math.min(...numericValues) const maxValue = Math.max(...numericValues) return minValue === maxValue - ? `${minValue}${attrUnits ? ` ${attrUnits}` : ""}` - : `${minValue}-${maxValue}${attrUnits ? ` ${attrUnits}` : ""}` + ? `${minValue}${attrUnits ? ` ${attrUnits}` : ""}` + : `${minValue}-${maxValue}${attrUnits ? ` ${attrUnits}` : ""}` } - + const getCategoricalSummary = (uniqueValues: Set): string => { const uniqueValuesArray = Array.from(uniqueValues) if (uniqueValuesArray.length === 1) { @@ -58,15 +87,15 @@ export const CaseCardModel = TileContentModel return `${uniqueValuesArray.length} values` } } - + if (self.summarizedCollections.includes(collection.id)) { const summaryMap = collection?.attributes.reduce((acc: Record, attr) => { if (!attr || !attr.id) return acc const selectedCases = self.data?.selection const casesToUse = selectedCases && selectedCases.size >= 1 - ? Array.from(selectedCases).map((id) => ({ __id__: id })) - : collection.cases + ? Array.from(selectedCases).map((id) => ({ __id__: id })) + : collection.cases const allValues = casesToUse.map(c => self.data?.getValue(c.__id__, attr.id)) const uniqueValues = new Set(allValues) const isNumeric = attr.numValues?.some((v, i) => attr.isNumeric(i)) @@ -78,7 +107,7 @@ export const CaseCardModel = TileContentModel summary = getNumericSummary(numericValues, attrUnits) } else { summary = getCategoricalSummary(uniqueValues) - } + } return { ...acc, [attr.id]: summary } }, {}) return collection?.attributes.map(attr => attr?.id && summaryMap[attr.id]) ?? [] @@ -87,11 +116,6 @@ export const CaseCardModel = TileContentModel } } })) - .actions(self => ({ - setSummarizedCollections(collections: string[]) { - self.summarizedCollections.replace(collections) - } - })) .actions(self => ({ setAttributeColumnWidth(collectionId: string, width?: number) { if (width) { @@ -101,48 +125,50 @@ export const CaseCardModel = TileContentModel self.attributeColumnWidths.delete(collectionId) } }, - addNewCase(cases: IGroupedCase[], collection: ICollectionModel, displayedCaseId: string) { + addNewCase() { const newCase: ICaseCreation = {} + const selectedCases = self.data?.selection - collection.allParentDataAttrs.forEach(attr => { - if (attr?.id) { - const value = self.data?.getValue(displayedCaseId, attr.id) - newCase[attr.id] = value + function findCommonCases(lineages: (readonly string[])[]) { + if (lineages.length === 0) return [] + if (lineages.length === 1) return lineages[0].slice(0, -1) + let commonValues = lineages[0] + for (let i = 1; i < lineages.length; i++) { + commonValues = commonValues.filter(value => lineages[i].includes(value)) + if (commonValues.length === 0) { + return [] + } } - }) + return commonValues + } + + if (selectedCases) { + const caseLineages = Array.from(selectedCases).map(caseId => self.caseLineage(caseId) || []) + const commonCaseIds = findCommonCases(caseLineages) + if (commonCaseIds.length > 0) { + commonCaseIds.forEach(caseId => { + const caseCollection = self.data?.getCollectionForCase(caseId) + caseCollection?.attributes.forEach(attr => { + const attrId = attr?.id + if (!attrId) return + const caseValue = self.data?.getValue(caseId, attr.id) + newCase[attrId] = caseValue + }) + }) + } + } const [newCaseId] = self.data?.addCases([newCase]) ?? [] // TODO: Figure out why this call to validateCases is necessary. The Cypress test for adding a case // fails if it isn't here, though adding a case seems to work fine when tested manually. self.data?.validateCases() - - return newCaseId - }, - setShowSummary(show: boolean, collectionId?: string) { - if (show) { - self.data?.setSelectedCases([]) - } - - const updatedSummarizedCollections = show - ? collectionId - ? [...self.summarizedCollections, collectionId] - : self.data?.collections.map(c => c.id) ?? [] - : collectionId - ? self.summarizedCollections.filter(cid => cid !== collectionId) - : [] - self.setSummarizedCollections(updatedSummarizedCollections) - }, - summarizeAllCollections() { - self.setSummarizedCollections(self.data?.collections.map(c => c.id) ?? []) - }, - updateAfterSharedModelChanges(sharedModel?: ISharedModel) { - // TODO - }, + return newCaseId + } })) -export interface ICaseCardModel extends Instance {} -export interface ICaseCardSnapshot extends SnapshotIn {} +export interface ICaseCardModel extends Instance { } +export interface ICaseCardSnapshot extends SnapshotIn { } export function isCaseCardModel(model?: ITileContentModel): model is ICaseCardModel { return model?.type === kCaseCardTileType diff --git a/v3/src/components/case-card/case-view.tsx b/v3/src/components/case-card/case-view.tsx index 4c87e94f22..397e45d75f 100644 --- a/v3/src/components/case-card/case-view.tsx +++ b/v3/src/components/case-card/case-view.tsx @@ -1,20 +1,19 @@ -import React, { useCallback, useMemo } from "react" +import React, { useCallback } from "react" import { observer } from "mobx-react-lite" import { IGroupedCase } from "../../models/data/data-set-types" import { ICollectionModel } from "../../models/data/collection" import { CaseAttrsView } from "./case-attrs-view" import { useCaseCardModel } from "./use-case-card-model" import { CollectionContext, ParentCollectionContext, useCollectionContext } from "../../hooks/use-collection-context" -import { CollectionTitle } from "../case-tile-common/collection-title" import { t } from "../../utilities/translation/translate" import { IAttribute } from "../../models/data/attribute" -import { createAttributesNotification, createCasesNotification } from "../../models/data/data-set-notifications" +import { createAttributesNotification } from "../../models/data/data-set-notifications" import { uiState } from "../../models/ui-state" import { uniqueName } from "../../utilities/js-utils" import { IDataSet } from "../../models/data/data-set" import { CaseCardCollectionSpacer } from "./case-card-collection-spacer" +import { CaseCardHeader } from "./case-card-header" -import Arrow from "../../assets/icons/arrow.svg" import AddIcon from "../../assets/icons/add-data-icon.svg" import "./case-view.scss" @@ -22,7 +21,7 @@ import "./case-view.scss" interface ICaseViewProps { cases: IGroupedCase[] level: number - onSelectCases: (caseIds: string[], collection: string) => void + onSelectCases: (caseIds: string[]) => void displayedCaseLineage?: readonly string[] onNewCollectionDrop: (dataSet: IDataSet, attrId: string, beforeCollectionId: string) => void } @@ -37,62 +36,17 @@ export const CaseView = observer(function CaseView(props: ICaseViewProps) { const {cases, level, onSelectCases, onNewCollectionDrop, displayedCaseLineage = []} = props const cardModel = useCaseCardModel() const data = cardModel?.data - const selectedCases = data?.selection - const selectionContainsCollectionCases = selectedCases && cases.some(c => selectedCases.has(c.__id__)) - const summaryTotal = selectionContainsCollectionCases ? selectedCases.size : cases.length const collectionId = useCollectionContext() const collection = data?.getCollection(collectionId) - const isCollectionSummarized = !!cardModel?.summarizedCollections.includes(collectionId) const initialSelectedCase = collection?.cases.find(c => c.__id__ === displayedCaseLineage[level]) const displayedCase = initialSelectedCase ?? cases[0] const displayedCaseId = displayedCase?.__id__ - const displayedCaseIndex = useMemo(() => { - // the first time this runs selectedCase will not be defined and this will return -1, thus the Math.max - return Math.max(0, cases.findIndex(c => c.__id__ === displayedCaseId)) - }, [cases, displayedCaseId]) - - const caseIndexText = isCollectionSummarized - ? `${summaryTotal} ${summaryTotal === 1 ? t("DG.DataContext.singleCaseName") : t("DG.DataContext.pluralCaseName")}` - : `${displayedCaseIndex + 1} of ${cases.length}` - const prevButtonDisabled = displayedCaseIndex <= 0 - const nextButtonDisabled = displayedCaseIndex >= cases.length - 1 - const handleNewCollectionDrop = useCallback((dataSet: IDataSet, attrId: string, collId: string) => { const attr = dataSet.attrFromID(attrId) attr && onNewCollectionDrop(dataSet, attrId, collId) }, [onNewCollectionDrop]) - const handleSelectCase = useCallback((delta: number) => () => { - const selectedCaseIndex = isCollectionSummarized - ? delta < 0 ? cases.length - 1 : 0 - : displayedCaseIndex + delta - const newCase = cases[selectedCaseIndex] - if (!newCase.__id__) return - - onSelectCases([newCase.__id__], collectionId) - }, [isCollectionSummarized, cases, displayedCaseIndex, onSelectCases, collectionId]) - - const handleAddNewCase = () => { - if (collection) { - let newCaseId: string | undefined - data?.applyModelChange(() => { - const newItemId = cardModel?.addNewCase(cases, collection, displayedCaseId) - newCaseId = newItemId && data?.getItemCaseIds(newItemId)[level] - newCaseId && onSelectCases([newCaseId], collectionId) - }, { - notify: () => { - if (newCaseId) { - return createCasesNotification([newCaseId], data) - } - }, - undoStringKey: "DG.Undo.caseTable.createNewCase", - redoStringKey: "DG.Redo.caseTable.createNewCase" - }) - cardModel?.setShowSummary(false) - } - } - const handleAddNewAttribute = () => { let attribute: IAttribute | undefined data?.applyModelChange(() => { @@ -133,42 +87,16 @@ export const CaseView = observer(function CaseView(props: ICaseViewProps) { <>
{level === 0 && } -
-
- -
-
- - - {caseIndexText} - - -
-
- -
-
+
- + { collection?.child && <>