Skip to content

Commit

Permalink
PR updates
Browse files Browse the repository at this point in the history
  • Loading branch information
emilys314 committed Sep 20, 2024
1 parent 1ff42d6 commit 66cb7f8
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@ import {
LabelGroup,
Popover,
} from '@patternfly/react-core';
import { getDescriptionFromK8sResource } from '~/concepts/k8s/utils';
import { getDescriptionFromK8sResource, getDisplayNameFromK8sResource } from '~/concepts/k8s/utils';
import TruncatedText from '~/components/TruncatedText';
import { ConnectionTypeConfigMapObj } from './types';
import UnspecifiedValue from './fields/UnspecifiedValue';
import CategoryLabel from './CategoryLabel';

type Props = {
connectionType?: ConnectionTypeConfigMapObj;
connectionType: ConnectionTypeConfigMapObj;
isPreview: boolean;
};

export const ConnectionTypeDetailsHelperText: React.FC<Props> = ({ connectionType }) => {
const displayName =
connectionType && connectionType.metadata.annotations?.['openshift.io/display-name'];
const description = connectionType && getDescriptionFromK8sResource(connectionType);
export const ConnectionTypeDetailsHelperText: React.FC<Props> = ({ connectionType, isPreview }) => {
const displayName = isPreview
? connectionType.metadata.annotations?.['openshift.io/display-name']
: getDisplayNameFromK8sResource(connectionType);
const description = getDescriptionFromK8sResource(connectionType);

return (
<HelperText>
Expand Down Expand Up @@ -54,7 +56,7 @@ export const ConnectionTypeDetailsHelperText: React.FC<Props> = ({ connectionTyp
<DescriptionListGroup>
<DescriptionListTerm>Category</DescriptionListTerm>
<DescriptionListDescription>
{connectionType?.data?.category?.length ? (
{connectionType.data?.category?.length ? (
<LabelGroup>
{connectionType.data.category.map((category) => (
<CategoryLabel key={category} category={category} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import {
import { ConnectionTypeDetailsHelperText } from './ConnectionTypeDetailsHelperText';

type Props = {
obj?: ConnectionTypeConfigMapObj;
setObj?: (obj?: ConnectionTypeConfigMapObj) => void;
connectionType?: ConnectionTypeConfigMapObj;
setConnectionType?: (obj?: ConnectionTypeConfigMapObj) => void;
connectionTypes?: ConnectionTypeConfigMapObj[];
isPreview?: boolean;
connectionNameDesc?: K8sNameDescriptionFieldData;
Expand All @@ -30,24 +30,22 @@ type Props = {
setConnectionValues?: (values: { [key: string]: ConnectionTypeValueType }) => void;
};

const ConnectionTypePreview: React.FC<Props> = ({
obj,
setObj,
const ConnectionTypeForm: React.FC<Props> = ({
connectionType,
setConnectionType,
connectionTypes,
isPreview,
isPreview = false,
connectionNameDesc,
setConnectionNameDesc,
connectionValues,
setConnectionValues,
}) => {
const connectionTypeName = obj && obj.metadata.annotations?.['openshift.io/display-name'];

const options: TypeaheadSelectOption[] = React.useMemo(() => {
if (isPreview && connectionTypeName) {
if (isPreview && connectionType?.metadata.annotations?.['openshift.io/display-name']) {
return [

Check warning on line 45 in frontend/src/concepts/connectionTypes/ConnectionTypeForm.tsx

View check run for this annotation

Codecov / codecov/patch

frontend/src/concepts/connectionTypes/ConnectionTypeForm.tsx#L45

Added line #L45 was not covered by tests
{
value: connectionTypeName,
content: connectionTypeName,
value: '',
content: connectionType.metadata.annotations['openshift.io/display-name'],
isSelected: true,
},
];
Expand All @@ -56,11 +54,11 @@ const ConnectionTypePreview: React.FC<Props> = ({
return connectionTypes.map((t) => ({
value: getResourceNameFromK8sResource(t),
content: getDisplayNameFromK8sResource(t),
isSelected: t.metadata.name === obj?.metadata.name,
isSelected: t.metadata.name === connectionType?.metadata.name,
}));
}
return [];

Check warning on line 60 in frontend/src/concepts/connectionTypes/ConnectionTypeForm.tsx

View check run for this annotation

Codecov / codecov/patch

frontend/src/concepts/connectionTypes/ConnectionTypeForm.tsx#L60

Added line #L60 was not covered by tests
}, [isPreview, obj?.metadata.name, connectionTypes, connectionTypeName]);
}, [isPreview, connectionType?.metadata, connectionTypes]);

return (
<Form>
Expand All @@ -70,23 +68,25 @@ const ConnectionTypePreview: React.FC<Props> = ({
id="connection-type"
selectOptions={options}
onSelect={(_, selection) =>
setObj?.(connectionTypes?.find((c) => c.metadata.name === selection))
setConnectionType?.(connectionTypes?.find((c) => c.metadata.name === selection))
}
isDisabled={isPreview || connectionTypes?.length === 1}
placeholder={
isPreview && !connectionTypeName
isPreview && !connectionType?.metadata.annotations?.['openshift.io/display-name']
? 'Unspecified'

Check warning on line 76 in frontend/src/concepts/connectionTypes/ConnectionTypeForm.tsx

View check run for this annotation

Codecov / codecov/patch

frontend/src/concepts/connectionTypes/ConnectionTypeForm.tsx#L76

Added line #L76 was not covered by tests
: 'Select a type, or search by keyword or category'
}
toggleProps={
isPreview && !connectionTypeName ? { status: MenuToggleStatus.danger } : undefined
isPreview && !connectionType?.metadata.annotations?.['openshift.io/display-name']
? { status: MenuToggleStatus.danger }

Check warning on line 81 in frontend/src/concepts/connectionTypes/ConnectionTypeForm.tsx

View check run for this annotation

Codecov / codecov/patch

frontend/src/concepts/connectionTypes/ConnectionTypeForm.tsx#L81

Added line #L81 was not covered by tests
: undefined
}
/>
{(isPreview || obj?.metadata.name) && (
<ConnectionTypeDetailsHelperText connectionType={obj} />
{connectionType && (
<ConnectionTypeDetailsHelperText connectionType={connectionType} isPreview={isPreview} />
)}
</FormGroup>
{(isPreview || obj?.metadata.name) && (
{(isPreview || connectionType?.metadata.name) && (
<FormSection title="Connection details" style={{ marginTop: 0 }}>
<K8sNameDescriptionField
dataTestId="connection-name-desc"
Expand All @@ -111,7 +111,7 @@ const ConnectionTypePreview: React.FC<Props> = ({
onDataChange={setConnectionNameDesc}
/>
<ConnectionTypeFormFields
fields={obj?.data?.fields}
fields={connectionType?.data?.fields}
isPreview={isPreview}
connectionValues={connectionValues}
onChange={(field, value) => {
Expand All @@ -127,4 +127,4 @@ const ConnectionTypePreview: React.FC<Props> = ({
);
};

export default ConnectionTypePreview;
export default ConnectionTypeForm;
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
Divider,
DrawerContentBody,
} from '@patternfly/react-core';
import ConnectionTypePreview from '~/concepts/connectionTypes/ConnectionTypePreview';
import ConnectionTypeForm from '~/concepts/connectionTypes/ConnectionTypeForm';
import { ConnectionTypeConfigMapObj } from '~/concepts/connectionTypes/types';

type Props = {
Expand Down Expand Up @@ -53,7 +53,7 @@ const ConnectionTypePreviewDrawer: React.FC<Props> = ({ children, isExpanded, on
>
<Card isFlat isRounded>
<CardBody>
<ConnectionTypePreview isPreview obj={obj} />
<ConnectionTypeForm isPreview connectionType={obj} />
</CardBody>
</Card>
</DrawerContentBody>
Expand Down
41 changes: 38 additions & 3 deletions frontend/src/concepts/connectionTypes/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { ProjectKind } from '~/k8sTypes';
import { translateDisplayNameForK8s } from '~/concepts/k8s/utils';
import { K8sNameDescriptionFieldData } from '~/concepts/k8s/K8sNameDescriptionField/types';
import {
Connection,
ConnectionTypeConfigMap,
ConnectionTypeConfigMapObj,
ConnectionTypeDataField,
Expand Down Expand Up @@ -111,15 +115,46 @@ export const getCompatibleTypes = (envVars: string[]): CompatibleTypes[] =>
}, []);

export const getDefaultValues = (
connectionType?: ConnectionTypeConfigMapObj,
connectionType: ConnectionTypeConfigMapObj,
): { [key: string]: ConnectionTypeValueType } => {
const defaults: {
[key: string]: ConnectionTypeValueType;
} = {};
for (const field of connectionType?.data?.fields ?? []) {
if (isConnectionTypeDataField(field) && field.properties.defaultValue) {
for (const field of connectionType.data?.fields ?? []) {
if (isConnectionTypeDataField(field) && field.properties.defaultValue != null) {
defaults[field.envVar] = field.properties.defaultValue;

Check warning on line 125 in frontend/src/concepts/connectionTypes/utils.ts

View check run for this annotation

Codecov / codecov/patch

frontend/src/concepts/connectionTypes/utils.ts#L125

Added line #L125 was not covered by tests
}
}
return defaults;
};

export const assembleConnectionSecret = (
project: ProjectKind,
type: ConnectionTypeConfigMapObj,
nameDesc: K8sNameDescriptionFieldData,
values: {
[key: string]: ConnectionTypeValueType;
},
): Connection => {
const connectionValuesAsStrings = Object.fromEntries(
Object.entries(values).map(([key, value]) => [key, String(value)]),
);
return {
apiVersion: 'v1',
kind: 'Secret',
metadata: {
name: nameDesc.k8sName.value || translateDisplayNameForK8s(nameDesc.name),
namespace: project.metadata.name,
labels: {
'opendatahub.io/dashboard': 'true',
'opendatahub.io/managed': 'true',
},
annotations: {
'opendatahub.io/connection-type': type.metadata.name,
'openshift.io/display-name': nameDesc.name,
'openshift.io/description': nameDesc.description,
},
},
stringData: connectionValuesAsStrings,
};
};
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
import React from 'react';
import { Modal } from '@patternfly/react-core';
import DashboardModalFooter from '~/concepts/dashboard/DashboardModalFooter';
import ConnectionTypePreview from '~/concepts/connectionTypes/ConnectionTypePreview';
import ConnectionTypeForm from '~/concepts/connectionTypes/ConnectionTypeForm';
import {
Connection,
ConnectionTypeConfigMapObj,
ConnectionTypeFieldType,
ConnectionTypeValueType,
isConnectionTypeDataField,
} from '~/concepts/connectionTypes/types';
import { translateDisplayNameForK8s } from '~/concepts/k8s/utils';
import { ProjectKind, SecretKind } from '~/k8sTypes';
import { useK8sNameDescriptionFieldData } from '~/concepts/k8s/K8sNameDescriptionField/K8sNameDescriptionField';
import { K8sNameDescriptionFieldData } from '~/concepts/k8s/K8sNameDescriptionField/types';
import { getDefaultValues } from '~/concepts/connectionTypes/utils';
import { assembleConnectionSecret, getDefaultValues } from '~/concepts/connectionTypes/utils';

type Props = {
connection?: Connection;
connectionTypes?: ConnectionTypeConfigMapObj[];
project?: ProjectKind;
onClose: (refresh?: boolean) => void;
connectionTypes: ConnectionTypeConfigMapObj[];
project: ProjectKind;
onClose: (submitted?: boolean) => void;
onSubmit: (connection: Connection) => Promise<SecretKind>;
};

Expand All @@ -35,64 +33,51 @@ export const ManageConnectionModal: React.FC<Props> = ({

const enabledConnectionTypes = React.useMemo(
() =>
connectionTypes?.filter((t) => t.metadata.annotations?.['opendatahub.io/enabled'] === 'true'),
connectionTypes.filter((t) => t.metadata.annotations?.['opendatahub.io/enabled'] === 'true'),
[connectionTypes],
);

const [selectedConnectionType, setSelectedConnectionType] = React.useState<
ConnectionTypeConfigMapObj | undefined
>(enabledConnectionTypes?.length === 1 ? enabledConnectionTypes[0] : undefined);
>(enabledConnectionTypes.length === 1 ? enabledConnectionTypes[0] : undefined);
const { data: nameDescData, onDataChange: setNameDescData } = useK8sNameDescriptionFieldData();
const [connectionValues, setConnectionValues] = React.useState<{
[key: string]: ConnectionTypeValueType;
}>(() => {
if (connection?.data) {
return connection.data;

Check warning on line 48 in frontend/src/pages/projects/screens/detail/connections/ManageConnectionsModal.tsx

View check run for this annotation

Codecov / codecov/patch

frontend/src/pages/projects/screens/detail/connections/ManageConnectionsModal.tsx#L48

Added line #L48 was not covered by tests
}
if (enabledConnectionTypes?.length === 1) {
if (enabledConnectionTypes.length === 1) {
return getDefaultValues(enabledConnectionTypes[0]);
}
return {};
});

// if user changes connection types, don't discard previous entries in case of accident
const [previousEntries, setPreviousEntries] = React.useState<{
const previousValues = React.useRef<{
[connectionTypeName: string]: {
nameDesc: K8sNameDescriptionFieldData;
values: {
[key: string]: ConnectionTypeValueType;
};
[key: string]: ConnectionTypeValueType;
};
}>({});
const changeSelectionType = React.useCallback(
(type?: ConnectionTypeConfigMapObj) => {
// save previous connection values
if (selectedConnectionType) {
setPreviousEntries({
...previousEntries,
[selectedConnectionType.metadata.name]: {
nameDesc: nameDescData,
values: connectionValues,
},
});
previousValues.current[selectedConnectionType.metadata.name] = connectionValues;
// clear previous values
setNameDescData('name', '');
setNameDescData('description', '');
setConnectionValues({});
}
// load saved values?
if (type?.metadata.name && type.metadata.name in previousEntries) {
setNameDescData('name', previousEntries[type.metadata.name].nameDesc.name);
setNameDescData('description', previousEntries[type.metadata.name].nameDesc.description);
setConnectionValues(previousEntries[type.metadata.name].values);
} else {
if (type?.metadata.name && type.metadata.name in previousValues.current) {
setConnectionValues(previousValues.current[type.metadata.name]);
} else if (type) {
// first time load, so add default values
setConnectionValues(getDefaultValues(type));
}

setSelectedConnectionType(type);
},
[selectedConnectionType, previousEntries, nameDescData, connectionValues, setNameDescData],
[selectedConnectionType, connectionValues],
);

const isValid = React.useMemo(
Expand Down Expand Up @@ -122,32 +107,24 @@ export const ManageConnectionModal: React.FC<Props> = ({
submitLabel="Create"
onCancel={onClose}
onSubmit={() => {
const connectionValuesAsStrings = Object.fromEntries(
Object.entries(connectionValues).map(([key, value]) => [key, String(value)]),
);
const update: Connection = {
apiVersion: 'v1',
kind: 'Secret',
metadata: {
name: nameDescData.k8sName.value || translateDisplayNameForK8s(nameDescData.name),
namespace: project?.metadata.name ?? '',
labels: {
'opendatahub.io/dashboard': 'true',
'opendatahub.io/managed': 'true',
},
annotations: {
'opendatahub.io/connection-type': selectedConnectionType?.metadata.name ?? '',
'openshift.io/display-name': nameDescData.name,
'openshift.io/description': nameDescData.description,
},
},
stringData: connectionValuesAsStrings,
};

setIsSaving(true);
setError(undefined);

onSubmit(update)
// this shouldn't ever happen, but type safety
if (!selectedConnectionType) {
setError(new Error('No connection type selected'));
setIsSaving(false);
return;

Check warning on line 117 in frontend/src/pages/projects/screens/detail/connections/ManageConnectionsModal.tsx

View check run for this annotation

Codecov / codecov/patch

frontend/src/pages/projects/screens/detail/connections/ManageConnectionsModal.tsx#L115-L117

Added lines #L115 - L117 were not covered by tests
}

onSubmit(
assembleConnectionSecret(
project,
selectedConnectionType,
nameDescData,
connectionValues,
),
)
.then(() => {
onClose(true);
})
Expand All @@ -163,10 +140,10 @@ export const ManageConnectionModal: React.FC<Props> = ({
/>
}
>
<ConnectionTypePreview
<ConnectionTypeForm
connectionTypes={enabledConnectionTypes}
obj={selectedConnectionType}
setObj={changeSelectionType}
connectionType={selectedConnectionType}
setConnectionType={changeSelectionType}
connectionNameDesc={nameDescData}
setConnectionNameDesc={setNameDescData}
connectionValues={connectionValues}
Expand Down
Loading

0 comments on commit 66cb7f8

Please sign in to comment.