-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor association table in create page #4
base: 2.17/support-DQC
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,21 +29,31 @@ import S3Logo from '../../assets/s3_logo.svg'; | |
|
||
interface OpenSearchConnectionTableProps { | ||
isDashboardAdmin: boolean; | ||
connectionType: string; | ||
connectionType?: string; | ||
dataSourceConnections: DataSourceConnection[]; | ||
handleUnassignDataSources: (dataSources: DataSourceConnection[]) => Promise<void>; | ||
inCreatePage?: boolean; | ||
handleUnassignDataSources: (dataSources: DataSourceConnection[]) => Promise<void> | void; | ||
getSelectedItems?: (dataSources: DataSourceConnection[]) => void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer rename to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||
} | ||
|
||
export const OpenSearchConnectionTable = ({ | ||
isDashboardAdmin, | ||
connectionType, | ||
dataSourceConnections, | ||
handleUnassignDataSources, | ||
getSelectedItems, | ||
inCreatePage = false, | ||
}: OpenSearchConnectionTableProps) => { | ||
const [selectedItems, setSelectedItems] = useState<DataSourceConnection[]>([]); | ||
const [modalVisible, setModalVisible] = useState(false); | ||
const [popoversState, setPopoversState] = useState<Record<string, boolean>>({}); | ||
|
||
useEffect(() => { | ||
if (inCreatePage && getSelectedItems) { | ||
getSelectedItems(selectedItems); | ||
} | ||
}, [selectedItems, getSelectedItems, inCreatePage]); | ||
|
||
useEffect(() => { | ||
// Reset selected items when connectionType changes | ||
setSelectedItems([]); | ||
|
@@ -127,7 +137,7 @@ export const OpenSearchConnectionTable = ({ | |
{ | ||
field: 'name', | ||
name: i18n.translate('workspace.detail.dataSources.table.title', { | ||
defaultMessage: 'Title', | ||
defaultMessage: 'Data source', | ||
}), | ||
truncateText: true, | ||
render: (name: string, record) => { | ||
|
@@ -250,19 +260,31 @@ export const OpenSearchConnectionTable = ({ | |
|
||
return ( | ||
<> | ||
<EuiInMemoryTable | ||
items={filteredDataSources} | ||
itemId="id" | ||
columns={columns} | ||
selection={selection} | ||
search={search} | ||
key={connectionType} | ||
isSelectable={true} | ||
pagination={{ | ||
initialPageSize: 10, | ||
pageSizeOptions: [10, 20, 30], | ||
}} | ||
/> | ||
{inCreatePage ? ( | ||
<EuiInMemoryTable | ||
items={filteredDataSources} | ||
itemId="id" | ||
columns={columns} | ||
selection={selection} | ||
key={connectionType} | ||
isSelectable={true} | ||
/> | ||
) : ( | ||
<EuiInMemoryTable | ||
items={filteredDataSources} | ||
itemId="id" | ||
columns={columns} | ||
selection={selection} | ||
search={search} | ||
key={connectionType} | ||
isSelectable={true} | ||
pagination={{ | ||
initialPageSize: 10, | ||
pageSizeOptions: [10, 20, 30], | ||
}} | ||
/> | ||
)} | ||
|
||
<EuiSpacer /> | ||
{modalVisible && ( | ||
<EuiConfirmModal | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,149 +3,131 @@ | |
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import React, { useCallback, useEffect, useState } from 'react'; | ||
import React, { useState } from 'react'; | ||
import { | ||
EuiSmallButton, | ||
EuiCompressedFormRow, | ||
EuiSpacer, | ||
EuiFlexGroup, | ||
EuiFlexItem, | ||
EuiButtonIcon, | ||
EuiCompressedComboBox, | ||
EuiComboBoxOptionOption, | ||
EuiFormLabel, | ||
EuiText, | ||
EuiFlexItem, | ||
EuiSmallButton, | ||
EuiFlexGroup, | ||
} from '@elastic/eui'; | ||
import { i18n } from '@osd/i18n'; | ||
import { SavedObjectsStart } from '../../../../../core/public'; | ||
import { getDataSourcesList } from '../../utils'; | ||
import { DataSource } from '../../../common/types'; | ||
import { SavedObjectsStart, CoreStart } from '../../../../../core/public'; | ||
import { DataSourceConnection } from '../../../common/types'; | ||
import { WorkspaceFormError } from './types'; | ||
import { AssociationDataSourceModal } from '../workspace_detail/association_data_source_modal'; | ||
import { OpenSearchConnectionTable } from '../workspace_detail/opensearch_connections_table'; | ||
import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; | ||
import { WorkspaceClient } from '../../workspace_client'; | ||
|
||
export interface SelectDataSourcePanelProps { | ||
errors?: { [key: number]: WorkspaceFormError }; | ||
savedObjects: SavedObjectsStart; | ||
selectedDataSources: DataSource[]; | ||
onChange: (value: DataSource[]) => void; | ||
assignedDataSources: DataSourceConnection[]; | ||
onChange: (value: DataSourceConnection[]) => void; | ||
isDashboardAdmin: boolean; | ||
} | ||
|
||
export const SelectDataSourcePanel = ({ | ||
errors, | ||
onChange, | ||
selectedDataSources, | ||
assignedDataSources, | ||
savedObjects, | ||
isDashboardAdmin, | ||
}: SelectDataSourcePanelProps) => { | ||
const [dataSourcesOptions, setDataSourcesOptions] = useState<EuiComboBoxOptionOption[]>([]); | ||
useEffect(() => { | ||
if (!savedObjects) return; | ||
getDataSourcesList(savedObjects.client, ['*']).then((result) => { | ||
const options = result.map(({ title, id }) => ({ | ||
label: title, | ||
value: id, | ||
})); | ||
setDataSourcesOptions(options); | ||
}); | ||
}, [savedObjects, setDataSourcesOptions]); | ||
const handleAddNewOne = useCallback(() => { | ||
onChange?.([ | ||
...selectedDataSources, | ||
{ | ||
title: '', | ||
id: '', | ||
}, | ||
]); | ||
}, [onChange, selectedDataSources]); | ||
const [modalVisible, setModalVisible] = useState(false); | ||
const [selectedItems, setSelectedItems] = useState<DataSourceConnection[]>([]); | ||
const { | ||
services: { notifications, http }, | ||
} = useOpenSearchDashboards<{ CoreStart: CoreStart; workspaceClient: WorkspaceClient }>(); | ||
|
||
const handleSelect = useCallback( | ||
(selectedOptions, index) => { | ||
const newOption = selectedOptions[0] | ||
? // Select new data source | ||
{ | ||
title: selectedOptions[0].label, | ||
id: selectedOptions[0].value, | ||
} | ||
: // Click reset button | ||
{ | ||
title: '', | ||
id: '', | ||
}; | ||
const newSelectedOptions = [...selectedDataSources]; | ||
newSelectedOptions.splice(index, 1, newOption); | ||
const handleAssignDataSources = (dataSources: DataSourceConnection[]) => { | ||
setModalVisible(false); | ||
const savedDataSources: DataSourceConnection[] = [...assignedDataSources, ...dataSources]; | ||
onChange(savedDataSources); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the table already supported it by getting relatedConnections from datasources |
||
}; | ||
|
||
onChange(newSelectedOptions); | ||
}, | ||
[onChange, selectedDataSources] | ||
); | ||
const handleUnassignDataSources = (dataSources: DataSourceConnection[]) => { | ||
const savedDataSources = (assignedDataSources ?? [])?.filter( | ||
({ id }: DataSourceConnection) => !dataSources.some((item) => item.id === id) | ||
); | ||
onChange(savedDataSources); | ||
}; | ||
|
||
const renderTableContent = () => { | ||
return ( | ||
<OpenSearchConnectionTable | ||
isDashboardAdmin={isDashboardAdmin} | ||
dataSourceConnections={assignedDataSources} | ||
handleUnassignDataSources={handleUnassignDataSources} | ||
getSelectedItems={getSelectedItems} | ||
inCreatePage={true} | ||
connectionType="openSearchConnections" | ||
/> | ||
); | ||
}; | ||
|
||
const handleDelete = useCallback( | ||
(index) => { | ||
const newSelectedOptions = [...selectedDataSources]; | ||
newSelectedOptions.splice(index, 1); | ||
const associationButton = ( | ||
<EuiSmallButton | ||
iconType="plusInCircle" | ||
onClick={() => setModalVisible(true)} | ||
data-test-subj="workspace-creator-dataSources-assign-button" | ||
> | ||
{i18n.translate('workspace.form.selectDataSourcePanel.addNew', { | ||
defaultMessage: 'Add data sources', | ||
})} | ||
</EuiSmallButton> | ||
); | ||
|
||
onChange(newSelectedOptions); | ||
}, | ||
[onChange, selectedDataSources] | ||
const removeButton = ( | ||
<EuiSmallButton | ||
iconType="unlink" | ||
color="danger" | ||
onClick={() => { | ||
handleUnassignDataSources(selectedItems); | ||
}} | ||
data-test-subj="workspace-creator-dataSources-assign-button" | ||
> | ||
{i18n.translate('workspace.form.selectDataSourcePanel.remove', { | ||
defaultMessage: 'Remove selected', | ||
})} | ||
</EuiSmallButton> | ||
); | ||
|
||
const getSelectedItems = (currentSelectedItems: DataSourceConnection[]) => | ||
setSelectedItems(currentSelectedItems); | ||
|
||
return ( | ||
<div> | ||
<EuiFormLabel> | ||
{i18n.translate('workspace.form.selectDataSource.subTitle', { | ||
defaultMessage: 'Data source', | ||
})} | ||
<EuiText size="xs"> | ||
{i18n.translate('workspace.form.selectDataSource.subTitle', { | ||
defaultMessage: 'Add data sources that will be available in the workspace', | ||
})} | ||
</EuiText> | ||
</EuiFormLabel> | ||
<EuiSpacer size="s" /> | ||
{selectedDataSources.map(({ id, title }, index) => ( | ||
<EuiCompressedFormRow | ||
key={index} | ||
isInvalid={!!errors?.[index]} | ||
error={errors?.[index]?.message} | ||
fullWidth | ||
> | ||
<EuiFlexGroup alignItems="flexEnd" gutterSize="m"> | ||
<EuiFlexItem style={{ maxWidth: 400 }}> | ||
<EuiCompressedComboBox | ||
data-test-subj="workspaceForm-select-dataSource-comboBox" | ||
singleSelection | ||
options={dataSourcesOptions} | ||
selectedOptions={ | ||
id | ||
? [ | ||
{ | ||
label: title, | ||
value: id, | ||
}, | ||
] | ||
: [] | ||
} | ||
onChange={(selectedOptions) => handleSelect(selectedOptions, index)} | ||
placeholder="Select" | ||
/> | ||
</EuiFlexItem> | ||
<EuiFlexItem style={{ maxWidth: 332 }}> | ||
<EuiButtonIcon | ||
color="danger" | ||
aria-label="Delete data source" | ||
iconType="trash" | ||
display="empty" | ||
size="m" | ||
onClick={() => handleDelete(index)} | ||
isDisabled={false} | ||
/> | ||
</EuiFlexItem> | ||
</EuiFlexGroup> | ||
</EuiCompressedFormRow> | ||
))} | ||
|
||
<EuiSmallButton | ||
fill | ||
fullWidth={false} | ||
onClick={handleAddNewOne} | ||
data-test-subj={`workspaceForm-select-dataSource-addNew`} | ||
> | ||
{i18n.translate('workspace.form.selectDataSourcePanel.addNew', { | ||
defaultMessage: 'Add New', | ||
})} | ||
</EuiSmallButton> | ||
<EuiSpacer size="m" /> | ||
<EuiFlexGroup alignItems="center"> | ||
{isDashboardAdmin && selectedItems.length > 0 && assignedDataSources.length > 0 && ( | ||
<EuiFlexItem grow={false}>{removeButton}</EuiFlexItem> | ||
)} | ||
{isDashboardAdmin && <EuiFlexItem grow={false}>{associationButton}</EuiFlexItem>} | ||
</EuiFlexGroup> | ||
<EuiSpacer size="xs" /> | ||
<EuiFlexItem style={{ maxWidth: 800 }}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems the maxWidth was 768 in design. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||
{assignedDataSources.length > 0 && renderTableContent()} | ||
</EuiFlexItem> | ||
{modalVisible && ( | ||
<AssociationDataSourceModal | ||
savedObjects={savedObjects} | ||
assignedConnections={assignedDataSources} | ||
closeModal={() => setModalVisible(false)} | ||
handleAssignDataSourceConnections={handleAssignDataSources} | ||
http={http} | ||
notifications={notifications} | ||
/> | ||
)} | ||
</div> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,7 @@ import { | |
getUseCaseFeatureConfig, | ||
isUseCaseFeatureConfig, | ||
} from '../../utils'; | ||
import { DataSource } from '../../../common/types'; | ||
import { DataSourceConnection } from '../../../common/types'; | ||
import { WorkspaceFormProps, WorkspaceFormErrors, WorkspacePermissionSetting } from './types'; | ||
import { | ||
appendDefaultFeatureIds, | ||
|
@@ -52,7 +52,7 @@ export const useWorkspaceForm = ({ | |
Array<Pick<WorkspacePermissionSetting, 'id'> & Partial<WorkspacePermissionSetting>> | ||
>(initialPermissionSettingsRef.current); | ||
|
||
const [selectedDataSources, setSelectedDataSources] = useState<DataSource[]>( | ||
const [selectedDataSources, setSelectedDataSources] = useState<DataSourceConnection[]>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we keep using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't find related changes in that branch, can you paste me the code line by URL? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My apologies, I made a mistake. |
||
defaultValues?.selectedDataSources && defaultValues.selectedDataSources.length > 0 | ||
? defaultValues.selectedDataSources | ||
: [] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my perspective, can remove
Promise<void>
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const handleAssignDataSourceConnections = async (
in detail page may need thisThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can try to remove it. The type should work fine. Because we doesn't await
handleAssignDataSourceConnections
inside modal component.