Skip to content

Commit

Permalink
feat: add Back button to extra options (#15300)
Browse files Browse the repository at this point in the history
* fix: add icons (#15122)

* added alerts

* revisions

* added icon

* spinner

* first draft

* working

* added back button to create modal

* revisions and testing
  • Loading branch information
AAfghahi authored Jun 22, 2021
1 parent d9d863b commit e7f71f3
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const ModalHeader = ({
db,
dbName,
dbModel,
editNewDb,
}: {
isLoading: boolean;
isEditMode: boolean;
Expand All @@ -58,6 +59,7 @@ const ModalHeader = ({
db: Partial<DatabaseObject> | null;
dbName: string;
dbModel: DatabaseForm;
editNewDb?: boolean;
}) => {
const isEditHeader = (
<>
Expand Down Expand Up @@ -102,7 +104,14 @@ const ModalHeader = ({
<p className="helper"> Step 2 of 3 </p>
<h4>Enter the required {dbModel.name} credentials</h4>
<p className="helper">
Need help? Learn more about connecting to {dbModel.name}.
Need help? Learn more about{' '}
<a
href={documentationLink(db?.engine)}
target="_blank"
rel="noopener noreferrer"
>
connecting to {dbModel.name}.
</a>
</p>
</StyledFormHeader>
);
Expand All @@ -122,10 +131,10 @@ const ModalHeader = ({
if (useSqlAlchemyForm) {
return useSqlAlchemyFormHeader;
}
if (hasConnectedDb) {
if (hasConnectedDb && !editNewDb) {
return hasConnectedDbHeader;
}
if (db) {
if (db || editNewDb) {
return hasDbHeader;
}
return noDbHeader;
Expand Down
158 changes: 106 additions & 52 deletions superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({
] = useDatabaseValidation();
const [hasConnectedDb, setHasConnectedDb] = useState<boolean>(false);
const [dbName, setDbName] = useState('');
const [editNewDb, setEditNewDb] = useState<boolean>(false);
const [isLoading, setLoading] = useState<boolean>(false);
const conf = useCommonConf();
const dbImages = getDatabaseImages();
Expand Down Expand Up @@ -350,6 +351,7 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({
setDB({ type: ActionType.reset });
setHasConnectedDb(false);
setValidationErrors(null); // reset validation errors on close
setEditNewDb(false);
onHide();
};

Expand Down Expand Up @@ -406,7 +408,9 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({
if (onDatabaseAdd) {
onDatabaseAdd();
}
onClose();
if (!editNewDb) {
onClose();
}
}
} else if (db) {
// Create
Expand Down Expand Up @@ -439,6 +443,7 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({
}
}
}
setEditNewDb(false);
setLoading(false);
};

Expand Down Expand Up @@ -538,10 +543,19 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({
</div>
);

const renderModalFooter = () =>
db // if db show back + connect
? [
!hasConnectedDb && (
const handleBackButtonOnFinish = () => {
if (dbFetched) {
fetchResource(dbFetched.id as number);
}
setEditNewDb(true);
};

const renderModalFooter = () => {
if (db) {
// if db show back + connenct
if (!hasConnectedDb || editNewDb) {
return (
<>
<StyledFooterButton
key="back"
onClick={() => {
Expand All @@ -550,26 +564,34 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({
>
Back
</StyledFooterButton>
),
!hasConnectedDb ? ( // if hasConnectedDb show back + finish
<StyledFooterButton
key="submit"
buttonStyle="primary"
onClick={onSave}
>
Connect
</StyledFooterButton>
) : (
<StyledFooterButton
key="submit"
buttonStyle="primary"
onClick={onClose}
>
Finish
</StyledFooterButton>
),
]
: [];
</>
);
}

return (
<>
<StyledFooterButton key="back" onClick={handleBackButtonOnFinish}>
Back
</StyledFooterButton>
<StyledFooterButton
key="submit"
buttonStyle="primary"
onClick={onClose}
>
Finish
</StyledFooterButton>
</>
);
}
return [];
};

const renderEditModalFooter = () => (
<>
Expand Down Expand Up @@ -614,6 +636,68 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({
setTabKey(key);
};

const renderFinishState = () => {
if (!editNewDb) {
return (
<ExtraOptions
db={db as DatabaseObject}
onInputChange={({ target }: { target: HTMLInputElement }) =>
onChange(ActionType.inputChange, {
type: target.type,
name: target.name,
checked: target.checked,
value: target.value,
})
}
onTextChange={({ target }: { target: HTMLTextAreaElement }) =>
onChange(ActionType.textChange, {
name: target.name,
value: target.value,
})
}
onEditorChange={(payload: { name: string; json: any }) =>
onChange(ActionType.editorChange, payload)
}
onExtraInputChange={({ target }: { target: HTMLInputElement }) => {
onChange(ActionType.extraInputChange, {
type: target.type,
name: target.name,
checked: target.checked,
value: target.value,
});
}}
onExtraEditorChange={(payload: { name: string; json: any }) =>
onChange(ActionType.extraEditorChange, payload)
}
/>
);
}
return (
<DatabaseConnectionForm
isEditMode
sslForced={sslForced}
dbModel={dbModel}
db={dbFetched as DatabaseObject}
onParametersChange={({ target }: { target: HTMLInputElement }) =>
onChange(ActionType.parametersChange, {
type: target.type,
name: target.name,
checked: target.checked,
value: target.value,
})
}
onChange={({ target }: { target: HTMLInputElement }) =>
onChange(ActionType.textChange, {
name: target.name,
value: target.value,
})
}
getValidation={() => getValidation(db)}
validationErrors={validationErrors}
/>
);
};

const isDynamic = (engine: string | undefined) =>
availableDbs?.databases.filter(
(DB: DatabaseObject) => DB.backend === engine || DB.engine === engine,
Expand Down Expand Up @@ -808,39 +892,9 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({
db={db}
dbName={dbName}
dbModel={dbModel}
editNewDb={editNewDb}
/>

<ExtraOptions
db={db as DatabaseObject}
onInputChange={({ target }: { target: HTMLInputElement }) =>
onChange(ActionType.inputChange, {
type: target.type,
name: target.name,
checked: target.checked,
value: target.value,
})
}
onTextChange={({ target }: { target: HTMLTextAreaElement }) =>
onChange(ActionType.textChange, {
name: target.name,
value: target.value,
})
}
onEditorChange={(payload: { name: string; json: any }) =>
onChange(ActionType.editorChange, payload)
}
onExtraInputChange={({ target }: { target: HTMLInputElement }) => {
onChange(ActionType.extraInputChange, {
type: target.type,
name: target.name,
checked: target.checked,
value: target.value,
});
}}
onExtraEditorChange={(payload: { name: string; json: any }) =>
onChange(ActionType.extraEditorChange, payload)
}
/>
{renderFinishState()}
</>
) : (
<>
Expand Down Expand Up @@ -876,8 +930,8 @@ const DatabaseModal: FunctionComponent<DatabaseModalProps> = ({
css={(theme: SupersetTheme) => antDAlertStyles(theme)}
type="info"
showIcon
message={t('Whitelisting IPs')}
description={connectionAlert.WHITELISTED_IPS}
message={t('IP Allowlist')}
description={connectionAlert.ALLOWED_IPS}
/>
)}
<DatabaseConnectionForm
Expand Down
11 changes: 11 additions & 0 deletions superset/db_engine_specs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,17 @@ def validate_parameters(
port = parameters.get("port", None)
if not port:
return errors
try:
port = int(port)
except (ValueError, TypeError):
errors.append(
SupersetError(
message="Port must be a valid integer.",
error_type=SupersetErrorType.CONNECTION_INVALID_PORT_ERROR,
level=ErrorLevel.ERROR,
extra={"invalid": ["port"]},
),
)
if not (isinstance(port, int) and 0 <= port < 2 ** 16):
errors.append(
SupersetError(
Expand Down
18 changes: 16 additions & 2 deletions tests/databases/api_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1807,7 +1807,9 @@ def test_validate_parameters_invalid_port(self):
assert response == {
"errors": [
{
"message": "Port must be a valid integer.",
"error_type": "CONNECTION_INVALID_PORT_ERROR",
"level": "error",
"extra": {
"invalid": ["port"],
"issue_codes": [
Expand All @@ -1817,9 +1819,21 @@ def test_validate_parameters_invalid_port(self):
}
],
},
"level": "error",
},
{
"error_type": "CONNECTION_INVALID_PORT_ERROR",
"message": "The port must be an integer between 0 and 65535 (inclusive).",
}
"level": "error",
"extra": {
"invalid": ["port"],
"issue_codes": [
{
"code": 1021,
"message": "Issue 1021 - Port number is invalid.",
}
],
},
},
]
}

Expand Down

0 comments on commit e7f71f3

Please sign in to comment.