diff --git a/src/messages.ts b/src/messages.ts index 1620914b5b..06f7ffd519 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -10,6 +10,10 @@ const messages = defineMessages({ id: 'authoring.alert.support.text', defaultMessage: 'Support Page', }, + unknownError: { + id: 'authoring.alert.error.unknown', + defaultMessage: 'Unknown error', + }, }); export default messages; diff --git a/src/taxonomy/data/apiHooks.ts b/src/taxonomy/data/apiHooks.ts index 479cc2c4db..e0cd927598 100644 --- a/src/taxonomy/data/apiHooks.ts +++ b/src/taxonomy/data/apiHooks.ts @@ -13,7 +13,6 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { camelCaseObject } from '@edx/frontend-platform'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; -import { useIntl } from '@edx/frontend-platform/i18n'; import { apiUrls, ALL_TAXONOMIES, getApiErrorMessage } from './api'; import * as api from './api'; import type { QueryOptions, TagListData } from './types'; @@ -214,18 +213,13 @@ export const useSubTags = (taxonomyId: number, parentTagValue: string) => useQue export const useCreateTag = (taxonomyId: number) => { const queryClient = useQueryClient(); - const intl = useIntl(); return useMutation({ mutationFn: async ({ value, parentTagValue }: { value: string, parentTagValue?: string }) => { - try { - await getAuthenticatedHttpClient().post( - apiUrls.createTag(taxonomyId), - { tag: value, parent_tag_value: parentTagValue }, - ); - } catch (err) { - throw new Error(getApiErrorMessage(err, intl)); - } + await getAuthenticatedHttpClient().post( + apiUrls.createTag(taxonomyId), + { tag: value, parent_tag_value: parentTagValue }, + ); }, onSuccess: () => { queryClient.invalidateQueries({ @@ -246,14 +240,10 @@ export const useUpdateTag = (taxonomyId: number) => { return useMutation({ mutationFn: async ({ value, originalValue }: { value: string, originalValue: string }) => { - try { - await getAuthenticatedHttpClient().patch( - apiUrls.updateTag(taxonomyId), - { tag: originalValue, updated_tag_value: value }, - ); - } catch (err) { - throw new Error(getApiErrorMessage(err)); - } + await getAuthenticatedHttpClient().patch( + apiUrls.updateTag(taxonomyId), + { tag: originalValue, updated_tag_value: value }, + ); }, onSuccess: () => { queryClient.invalidateQueries({ diff --git a/src/taxonomy/tag-list/OptionalExpandLink.tsx b/src/taxonomy/tag-list/OptionalExpandLink.tsx index edfa6580f2..e42c198dcb 100644 --- a/src/taxonomy/tag-list/OptionalExpandLink.tsx +++ b/src/taxonomy/tag-list/OptionalExpandLink.tsx @@ -4,7 +4,7 @@ import { ExpandLess, ExpandMore } from '@openedx/paragon/icons'; import { Row } from '@tanstack/react-table'; import { useIntl } from '@edx/frontend-platform/i18n'; -import type { TreeRowData } from '../tree-table/types'; +import type { TreeRowData } from '@src/taxonomy/tree-table/types'; import messages from './messages'; interface OptionalExpandLinkProps { diff --git a/src/taxonomy/tag-list/TagListTable.tsx b/src/taxonomy/tag-list/TagListTable.tsx index c9c80adb08..bd62f675e2 100644 --- a/src/taxonomy/tag-list/TagListTable.tsx +++ b/src/taxonomy/tag-list/TagListTable.tsx @@ -4,9 +4,9 @@ import React, { useEffect, } from 'react'; import type { PaginationState } from '@tanstack/react-table'; -import { useTagListData, useCreateTag, useUpdateTag } from '../data/apiHooks'; +import { TableView } from '@src/taxonomy/tree-table'; +import { useTagListData, useCreateTag, useUpdateTag } from '@src/taxonomy/data/apiHooks'; import { TagTree } from './tagTree'; -import { TableView } from '../tree-table'; import type { RowId, TreeColumnDef, diff --git a/src/taxonomy/tag-list/UsageCountDisplay.tsx b/src/taxonomy/tag-list/UsageCountDisplay.tsx new file mode 100644 index 0000000000..97a95ad026 --- /dev/null +++ b/src/taxonomy/tag-list/UsageCountDisplay.tsx @@ -0,0 +1,25 @@ +import { + Bubble, +} from '@openedx/paragon'; +import type { Row } from '@tanstack/react-table'; +import type { + TreeRowData, +} from '@src/taxonomy/tree-table/types'; +import { TagListRowData } from './types'; + +const asTagListRowData = (row: Row): TagListRowData => ( + row.original as unknown as TagListRowData +); + +const UsageCountDisplay = ({ row }: { row: Row }) => { + const count = asTagListRowData(row).usageCount ?? 0; + return ( + count > 0 && ( + + {count} + + ) + ); +}; + +export default UsageCountDisplay; diff --git a/src/taxonomy/tag-list/hooks.ts b/src/taxonomy/tag-list/hooks.ts index 5484d88b0e..8ced5f3a5b 100644 --- a/src/taxonomy/tag-list/hooks.ts +++ b/src/taxonomy/tag-list/hooks.ts @@ -1,10 +1,11 @@ import { useReducer } from 'react'; import { useIntl } from '@edx/frontend-platform/i18n'; -import { useCreateTag, useUpdateTag } from '../data/apiHooks'; +import globalMessages from '@src/messages'; +import { useCreateTag, useUpdateTag } from '@src/taxonomy/data/apiHooks'; +import type { RowId } from '@src/taxonomy/tree-table/types'; import { TagTree } from './tagTree'; import { TagListTableError } from './errors'; -import type { RowId } from '../tree-table/types'; import { TABLE_MODES, TRANSITION_TABLE, @@ -163,6 +164,26 @@ const useEditActions = ({ return true; }; + const getErrorMessage = (error: any): string => { + let errorMessage: string = ''; + if (error.name === 'AxiosError') { + const responseData = error.response?.data; + const tagError = Object.entries(responseData)?.find((errItem: [string, unknown]) => ( + ['tag', 'value', 'updated_tag_value'].includes(errItem[0].toLowerCase()) + )); + + const errorMessages = tagError ? tagError[1] : ( + (error as Error).message || intl.formatMessage(globalMessages.unknownError) + ); + errorMessage = Array.isArray(errorMessages) ? errorMessages.join('; ') : String(errorMessages); + } else { + errorMessage = (error as Error).message || intl.formatMessage(globalMessages.unknownError); + } + + errorMessage = errorMessage.replace(/\.$/, ''); // Remove trailing period for better message formatting + return errorMessage; + }; + const handleCreateTag = async (value: string, parentTagValue?: string) => { const trimmed = value.trim(); @@ -182,9 +203,9 @@ const useEditActions = ({ setIsCreatingTopTag(false); setCreatingParentId(null); } catch (error) { - const message = intl.formatMessage(messages.tagCreationErrorMessage, { errorMessage: (error as Error)?.message }); - setDraftError((error as Error)?.message || intl.formatMessage(messages.tagCreationErrorMessage, { errorMessage: '' })); - setToast({ show: true, message }); + const errorMessage = getErrorMessage(error); + setDraftError(errorMessage); + setToast({ show: true, message: intl.formatMessage(messages.tagCreationErrorMessage, { errorMessage }) }); } }; @@ -211,9 +232,9 @@ const useEditActions = ({ message: intl.formatMessage(messages.tagUpdateSuccessMessage, { name: trimmed }), }); } catch (error) { - const message = intl.formatMessage(messages.tagUpdateErrorMessage, { errorMessage: (error as Error)?.message }); - setDraftError((error as Error)?.message || intl.formatMessage(messages.tagUpdateErrorMessage, { errorMessage: '' })); - setToast({ show: true, message }); + const errorMessage = getErrorMessage(error); + setDraftError(errorMessage); + setToast({ show: true, message: intl.formatMessage(messages.tagUpdateErrorMessage, { errorMessage }) }); } }; diff --git a/src/taxonomy/tag-list/tagColumns.tsx b/src/taxonomy/tag-list/tagColumns.tsx index 77ebc2341d..363a1a9a12 100644 --- a/src/taxonomy/tag-list/tagColumns.tsx +++ b/src/taxonomy/tag-list/tagColumns.tsx @@ -1,5 +1,4 @@ import { - Bubble, Icon, IconButton, IconButtonWithTooltip, @@ -12,24 +11,18 @@ import { import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n'; import type { Row } from '@tanstack/react-table'; -import messages from './messages'; import type { RowId, TreeColumnDef, TreeRowData, -} from '../tree-table/types'; +} from '@src/taxonomy/tree-table/types'; +import { TagListRowData } from './types'; +import messages from './messages'; import OptionalExpandLink from './OptionalExpandLink'; +import UsageCountDisplay from './UsageCountDisplay'; const EDITABLE_COLUMNS = ['value']; -interface TagListRowData extends TreeRowData { - depth: number; - childCount: number; - usageCount?: number; - isNew?: boolean; - isEditing?: boolean; -} - const asTagListRowData = (row: Row): TagListRowData => ( row.original as unknown as TagListRowData ); @@ -49,17 +42,6 @@ interface GetColumnsArgs { maxDepth: number; } -const UsageCountDisplay = ({ row }: { row: Row }) => { - const count = asTagListRowData(row).usageCount ?? 0; - return ( - count > 0 && ( - - {count} - - ) - ); -}; - interface ActionsHeaderProps { onStartDraft: () => void; setDraftError: (error: string) => void; diff --git a/src/taxonomy/tag-list/tagTree.ts b/src/taxonomy/tag-list/tagTree.ts index 06d43a04b6..f6cf9023c9 100644 --- a/src/taxonomy/tag-list/tagTree.ts +++ b/src/taxonomy/tag-list/tagTree.ts @@ -1,5 +1,5 @@ +import type { TagData } from '@src/taxonomy/data/types'; import { TagTreeError } from './errors'; -import type { TagData } from '../data/types'; export interface TagTreeNode extends TagData { subRows?: TagTreeNode[]; diff --git a/src/taxonomy/tag-list/types.ts b/src/taxonomy/tag-list/types.ts new file mode 100644 index 0000000000..845cee6956 --- /dev/null +++ b/src/taxonomy/tag-list/types.ts @@ -0,0 +1,9 @@ +import { TreeRowData } from '@src/taxonomy/tree-table/types'; + +export interface TagListRowData extends TreeRowData { + depth: number; + childCount: number; + usageCount?: number; + isNew?: boolean; + isEditing?: boolean; +} diff --git a/src/taxonomy/tree-table/CreateRow.test.tsx b/src/taxonomy/tree-table/CreateRow.test.tsx index dedfb12490..7510f3f3bb 100644 --- a/src/taxonomy/tree-table/CreateRow.test.tsx +++ b/src/taxonomy/tree-table/CreateRow.test.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { IntlProvider } from '@edx/frontend-platform/i18n'; import { fireEvent, render, screen } from '@testing-library/react'; -import { CreateRow } from './CreateRow'; +import CreateRow from './CreateRow'; const wrapper = ({ children }: { children: React.ReactNode }) => ( {children} @@ -15,7 +15,6 @@ const baseProps = () => ({ setIsCreatingTopRow: jest.fn(), exitDraftWithoutSave: jest.fn(), createRowMutation: { isPending: false }, - columns: [{ id: 'value' }], validate: jest.fn((value: string) => value.trim().length > 0), }); diff --git a/src/taxonomy/tree-table/CreateRow.tsx b/src/taxonomy/tree-table/CreateRow.tsx index 4091db0a56..f130560b02 100644 --- a/src/taxonomy/tree-table/CreateRow.tsx +++ b/src/taxonomy/tree-table/CreateRow.tsx @@ -1,24 +1,6 @@ -import React, { useState } from 'react'; -import { Button, Spinner } from '@openedx/paragon'; -import { useIntl } from '@edx/frontend-platform/i18n'; - -import { EditableCell } from './EditableCell'; -import type { CreateRowMutationState, TreeColumnDef } from './types'; -import messages from './messages'; - -interface DraftRowProps { - draftError: string; - initialValue?: string; - onSave: (value: string) => void; - onCancel: () => void; - mutationState: CreateRowMutationState; - columns: TreeColumnDef[]; - indent?: number; - validate: (value: string, mode?: 'soft' | 'hard') => boolean; - requireValueChangeToEnableSave?: boolean; - rowTestId?: string; - rowId?: string; -} +import React from 'react'; +import type { CreateRowMutationState } from './types'; +import DraftRow from './DraftRow'; interface CreateRowProps { draftError: string; @@ -27,118 +9,10 @@ interface CreateRowProps { setIsCreatingTopRow: (isCreating: boolean) => void; exitDraftWithoutSave: () => void; createRowMutation: CreateRowMutationState; - columns: TreeColumnDef[]; indent?: number; validate: (value: string, mode?: 'soft' | 'hard') => boolean; } -interface EditRowProps { - draftError: string; - setDraftError: (error: string) => void; - initialValue: string; - handleUpdateRow: (value: string) => void; - cancelEditRow: () => void; - updateRowMutation: CreateRowMutationState; - columns: TreeColumnDef[]; - indent?: number; - validate: (value: string, mode?: 'soft' | 'hard') => boolean; -} - -const DraftRow: React.FC = ({ - draftError, - initialValue = '', - onSave, - onCancel, - mutationState, - columns, - indent = 0, - validate, - requireValueChangeToEnableSave = false, - rowTestId, - rowId, -}) => { - const [rowValue, setRowValue] = useState(initialValue); - const [saveDisabled, setSaveDisabled] = useState(true); - const intl = useIntl(); - - const updateSaveDisabled = (value: string) => { - const trimmedValue = value.trim(); - const isValid = validate(value, 'soft'); - const isUnchanged = requireValueChangeToEnableSave && trimmedValue === initialValue.trim(); - setSaveDisabled(!isValid || !trimmedValue || isUnchanged || mutationState.isPending || false); - }; - - const handleValueChange = (e: React.ChangeEvent) => { - const { value } = e.target; - setRowValue(value); - updateSaveDisabled(value); - }; - - const handleSave = () => { - onSave(rowValue.trim()); - }; - - const handleValueCellKeyPress = (e: React.KeyboardEvent) => { - if (e.key === 'Enter' && !saveDisabled && !draftError) { - e.preventDefault(); - handleSave(); - return; - } - - if (e.key === 'Escape') { - e.preventDefault(); - onCancel(); - } - }; - - return ( - - -
- -
- - - - - - - - - - {mutationState.isPending && ( - - )} - - - - ); -}; - const CreateRow: React.FC = ({ draftError, setDraftError, @@ -146,7 +20,6 @@ const CreateRow: React.FC = ({ setIsCreatingTopRow, exitDraftWithoutSave, createRowMutation, - columns, indent = 0, validate, }) => { @@ -162,7 +35,6 @@ const CreateRow: React.FC = ({ onSave={handleCreateRow} onCancel={handleCancel} mutationState={createRowMutation} - columns={columns} indent={indent} validate={validate} rowId="creating-top-row" @@ -171,35 +43,4 @@ const CreateRow: React.FC = ({ ); }; -const EditRow: React.FC = ({ - draftError, - setDraftError, - initialValue, - handleUpdateRow, - cancelEditRow, - updateRowMutation, - columns, - indent = 0, - validate, -}) => { - const handleCancel = () => { - setDraftError(''); - cancelEditRow(); - }; - - return ( - - ); -}; - -export { CreateRow, EditRow }; +export default CreateRow; diff --git a/src/taxonomy/tree-table/DraftRow.tsx b/src/taxonomy/tree-table/DraftRow.tsx new file mode 100644 index 0000000000..f15bc4f4a5 --- /dev/null +++ b/src/taxonomy/tree-table/DraftRow.tsx @@ -0,0 +1,126 @@ +import React, { useState } from 'react'; +import { useIntl } from '@edx/frontend-platform/i18n'; +import { Button, Spinner } from '@openedx/paragon'; +import { Row } from '@tanstack/react-table'; + +import UsageCountDisplay from '@src/taxonomy/tag-list/UsageCountDisplay'; +import { EditableCell } from './EditableCell'; +import type { CreateRowMutationState, TreeRowData } from './types'; +import messages from './messages'; + +interface DraftRowProps { + draftError: string; + initialValue?: string; + onSave: (value: string) => void; + onCancel: () => void; + mutationState: CreateRowMutationState; + indent?: number; + validate: (value: string, mode?: 'soft' | 'hard') => boolean; + requireValueChangeToEnableSave?: boolean; + rowTestId?: string; + rowId?: string; + row?: Row; +} + +const DraftRow: React.FC = ({ + draftError, + initialValue = '', + onSave, + onCancel, + mutationState, + indent = 0, + validate, + requireValueChangeToEnableSave = false, + rowTestId, + rowId, + row, + +}) => { + const [rowValue, setRowValue] = useState(initialValue); + const [saveDisabled, setSaveDisabled] = useState(true); + const intl = useIntl(); + + const updateSaveDisabled = (value: string) => { + const trimmedValue = value.trim(); + const isValid = validate(value, 'soft'); + const isUnchanged = requireValueChangeToEnableSave && trimmedValue === initialValue.trim(); + setSaveDisabled(!isValid || !trimmedValue || isUnchanged || mutationState.isPending || false); + }; + + const handleValueChange = (e: React.ChangeEvent) => { + const { value } = e.target; + setRowValue(value); + updateSaveDisabled(value); + }; + + const handleSave = () => { + onSave(rowValue.trim()); + }; + + const handleValueCellKeyPress = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' && !saveDisabled && !draftError) { + e.preventDefault(); + handleSave(); + return; + } + + if (e.key === 'Escape') { + e.preventDefault(); + onCancel(); + } + }; + + const indentClass = indent > 0 ? `tree-table-indent tree-table-indent-${indent}` : ''; + + return ( + + +
+ +
+ + + {row ? : null} + + + + + + + + + + {mutationState.isPending && ( + + )} + + + + ); +}; + +export default DraftRow; diff --git a/src/taxonomy/tree-table/EditRow.tsx b/src/taxonomy/tree-table/EditRow.tsx new file mode 100644 index 0000000000..12a83fa055 --- /dev/null +++ b/src/taxonomy/tree-table/EditRow.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { Row } from '@tanstack/react-table'; +import type { CreateRowMutationState, TreeRowData } from './types'; +import DraftRow from './DraftRow'; + +interface EditRowProps { + draftError: string; + setDraftError: (error: string) => void; + initialValue: string; + handleUpdateRow: (value: string) => void; + cancelEditRow: () => void; + updateRowMutation: CreateRowMutationState; + indent?: number; + validate: (value: string, mode?: 'soft' | 'hard') => boolean; + row: Row; +} + +const EditRow: React.FC = ({ + draftError, + setDraftError, + initialValue, + handleUpdateRow, + cancelEditRow, + updateRowMutation, + indent = 0, + validate, + row, +}) => { + const handleCancel = () => { + setDraftError(''); + cancelEditRow(); + }; + + return ( + + ); +}; + +export default EditRow; diff --git a/src/taxonomy/tree-table/EditableCell.tsx b/src/taxonomy/tree-table/EditableCell.tsx index 8cdc10aabc..d4de95fa74 100644 --- a/src/taxonomy/tree-table/EditableCell.tsx +++ b/src/taxonomy/tree-table/EditableCell.tsx @@ -7,8 +7,9 @@ import React, { import { Form } from '@openedx/paragon'; import { useIntl } from '@edx/frontend-platform/i18n'; + +import OptionalExpandLink from '@src/taxonomy/tag-list/OptionalExpandLink'; import messages from './messages'; -import OptionalExpandLink from '../tag-list/OptionalExpandLink'; /** * Props for the EditableCell component. diff --git a/src/taxonomy/tree-table/NestedRows.tsx b/src/taxonomy/tree-table/NestedRows.tsx index 216bcfbf18..a0c42b5db8 100644 --- a/src/taxonomy/tree-table/NestedRows.tsx +++ b/src/taxonomy/tree-table/NestedRows.tsx @@ -7,7 +7,8 @@ import type { TreeColumnDef, CreateRowMutationState, } from './types'; -import { CreateRow, EditRow } from './CreateRow'; +import CreateRow from './CreateRow'; +import EditRow from './EditRow'; interface NestedRowsProps { /** The parent row object from TanStack React Table */ @@ -103,7 +104,6 @@ const NestedRows = ({ setIsCreatingTopRow={setIsCreatingTopRow} exitDraftWithoutSave={onCancelCreation} createRowMutation={createRowMutation} - columns={[]} indent={indent} validate={validate} /> @@ -123,9 +123,9 @@ const NestedRows = ({ exitDraftWithoutSave(); }} updateRowMutation={updateRowMutation} - columns={columns} indent={indent} validate={validate} + row={row} /> ) : ( @@ -137,7 +137,7 @@ const NestedRows = ({ return ( {isFirstColumn ? (
{content}
diff --git a/src/taxonomy/tree-table/SaveErrorAlert.tsx b/src/taxonomy/tree-table/SaveErrorAlert.tsx new file mode 100644 index 0000000000..4476e06c79 --- /dev/null +++ b/src/taxonomy/tree-table/SaveErrorAlert.tsx @@ -0,0 +1,42 @@ +import React, { useEffect } from 'react'; +import { + Alert, +} from '@openedx/paragon'; + +import { Info } from '@openedx/paragon/icons'; +import { useIntl } from '@edx/frontend-platform/i18n'; +import './TableView.scss'; +import messages from './messages'; + +interface SaveErrorAlertProps { + draftError: string | undefined; + isError: boolean | undefined; + isUpdateError: boolean | undefined; +} +const SaveErrorAlert = ({ draftError, isError, isUpdateError }: SaveErrorAlertProps) => { + const intl = useIntl(); + const hasError = (isError || isUpdateError) && !!draftError; + const [alertOpen, setAlertOpen] = React.useState(hasError); + + useEffect(() => { + if (hasError) { + setAlertOpen(true); + } + if (!hasError) { + setAlertOpen(false); + } + }, [hasError, isError, isUpdateError, draftError]); + + if (!alertOpen) { return null; } + + return ( + { setAlertOpen(false); }}> + + {intl.formatMessage(messages.errorSavingTitle)} + + {intl.formatMessage(messages.errorSavingMessage, { errorMessage: draftError }) } + + ); +}; + +export default SaveErrorAlert; diff --git a/src/taxonomy/tree-table/TableBody.tsx b/src/taxonomy/tree-table/TableBody.tsx index 6e1819a289..99fca02dd7 100644 --- a/src/taxonomy/tree-table/TableBody.tsx +++ b/src/taxonomy/tree-table/TableBody.tsx @@ -13,7 +13,8 @@ import type { TreeColumnDef, TreeTable, } from './types'; -import { CreateRow, EditRow } from './CreateRow'; +import CreateRow from './CreateRow'; +import EditRow from './EditRow'; interface TableBodyProps { columns: TreeColumnDef[]; @@ -86,7 +87,6 @@ const TableBody = ({ setIsCreatingTopRow={setIsCreatingTopRow} exitDraftWithoutSave={exitDraftWithoutSave} createRowMutation={createRowMutation} - columns={columns} validate={validate} /> )} @@ -104,14 +104,14 @@ const TableBody = ({ exitDraftWithoutSave(); }} updateRowMutation={updateRowMutation} - columns={columns} validate={validate} + row={row} /> ) : ( {row.getVisibleCells() - .map((cell, index) => ( - + .map((cell) => ( + {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} diff --git a/src/taxonomy/tree-table/TableView.tsx b/src/taxonomy/tree-table/TableView.tsx index 79aa625259..92ad3bd5fe 100644 --- a/src/taxonomy/tree-table/TableView.tsx +++ b/src/taxonomy/tree-table/TableView.tsx @@ -5,7 +5,6 @@ import { Card, ActionRow, Pagination, - Alert, Icon, } from '@openedx/paragon'; @@ -18,7 +17,7 @@ import { type PaginationState, } from '@tanstack/react-table'; -import { ArrowDropUpDown, Info } from '@openedx/paragon/icons'; +import { ArrowDropUpDown } from '@openedx/paragon/icons'; import { useIntl } from '@edx/frontend-platform/i18n'; import TableBody from './TableBody'; import './TableView.scss'; @@ -30,6 +29,7 @@ import type { TreeRowData, } from './types'; import messages from './messages'; +import SaveErrorAlert from './SaveErrorAlert'; interface TableViewProps { treeData: TreeRowData[]; @@ -102,18 +102,10 @@ const TableView = ({ const { isError } = createRowMutation; const { isError: isUpdateError } = updateRowMutation; - const [showError, setShowError] = React.useState(true); return ( <> - {(isError || isUpdateError) && showError && ( - setShowError(false)}> - - {intl.formatMessage(messages.errorSavingTitle)} - - {intl.formatMessage(messages.errorSavingMessage, { errorMessage: draftError || intl.formatMessage(messages.errorSavingMessage, { errorMessage: '' }) })} - - )} +
@@ -142,7 +134,7 @@ const TableView = ({ {headerGroup.headers.map((header, index) => ( {header.isPlaceholder ? null