create down migration when a column is dropped (close #2291) (#2385)

This commit is contained in:
Aravind Shankar 2019-06-26 18:42:44 +05:30 committed by Shahidh K Muhammed
parent b52ed4ccf0
commit c17bf2f94b
29 changed files with 257 additions and 373 deletions

View File

@ -1,6 +1,7 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"net/url" "net/url"
"strings" "strings"
@ -130,7 +131,7 @@ func MigrateAPI(c *gin.Context) {
c.JSON(http.StatusInternalServerError, &Response{Code: "internal_error", Message: err.Error()}) c.JSON(http.StatusInternalServerError, &Response{Code: "internal_error", Message: err.Error()})
return return
} }
c.JSON(http.StatusOK, &Response{Name: request.Name}) c.JSON(http.StatusOK, &Response{Name: fmt.Sprintf("%d_%s", timestamp, request.Name)})
default: default:
c.JSON(http.StatusMethodNotAllowed, &gin.H{"message": "Method not allowed"}) c.JSON(http.StatusMethodNotAllowed, &gin.H{"message": "Method not allowed"})
} }

View File

@ -234,8 +234,7 @@ export const passRemoveUniqueKey = () => {
}; };
export const passMTDeleteCol = () => { export const passMTDeleteCol = () => {
// cy.get(getElementFromAlias(`edit-${getColName(0)}`)).click(); cy.get(getElementFromAlias('modify-table-edit-column-1')).click();
// cy.wait(500);
cy.get(getElementFromAlias('modify-table-column-1-remove')).click(); cy.get(getElementFromAlias('modify-table-column-1-remove')).click();
cy.on('window:alert', str => { cy.on('window:alert', str => {
expect(str === 'Are you sure you want to delete?').to.be.true; expect(str === 'Are you sure you want to delete?').to.be.true;

View File

@ -40,31 +40,8 @@ const showNotification = ({
Notifications.show( Notifications.show(
{ {
position, position,
autoDismiss: level === 'error' ? 0 : 5, autoDismiss: ['error', 'warning'].includes(level) ? 0 : 5,
dismissible: level === 'error' ? 'click' : 'both', dismissible: ['error', 'warning'].includes(level) ? 'button' : 'both',
children: json ? jsonFormat(json) : null,
...options,
},
level
)
);
};
};
const showTempNotification = ({
level = 'info',
position = 'tr',
json,
...options
} = {}) => {
return dispatch => {
dispatch(Notifications.removeAll());
dispatch(
Notifications.show(
{
position,
autoDismiss: 2,
dismissible: 'both',
children: json ? jsonFormat(json) : null, children: json ? jsonFormat(json) : null,
...options, ...options,
}, },
@ -161,5 +138,4 @@ export {
notifExpand, notifExpand,
notifMsg, notifMsg,
showNotification, showNotification,
showTempNotification,
}; };

View File

@ -853,6 +853,10 @@ code {
background: #f2f2f2 !important; background: #f2f2f2 !important;
} }
.text_gray {
color: #767E96
}
.docsButton { .docsButton {
background-color: #fff; background-color: #fff;
border-radius: 5px; border-radius: 5px;

View File

@ -1,12 +1,12 @@
import React from 'react'; import React from 'react';
import AceEditor from 'react-ace'; import AceEditor from 'react-ace';
import { showNotification, showTempNotification } from '../../App/Actions'; import { showNotification } from '../../App/Actions';
import { notifExpand, notifMsg } from '../../App/Actions'; import { notifExpand, notifMsg } from '../../App/Actions';
import Button from '../../Common/Button/Button'; import Button from '../../Common/Button/Button';
const styles = require('../../Common/TableCommon/Table.scss'); const styles = require('../../Common/TableCommon/Table.scss');
const showErrorNotification = (title, message, reqBody, error) => { const showErrorNotification = (title, message, error) => {
let modMessage; let modMessage;
let refreshBtn; let refreshBtn;
@ -36,7 +36,7 @@ const showErrorNotification = (title, message, reqBody, error) => {
} else { } else {
modMessage = error.code; modMessage = error.code;
} }
} else if (error && 'internal' in error) { } else if (error && 'internal' in error && 'error' in error.internal) {
modMessage = error.code + ' : ' + error.internal.error.message; modMessage = error.code + ' : ' + error.internal.error.message;
} else if (error && 'custom' in error) { } else if (error && 'custom' in error) {
modMessage = error.custom; modMessage = error.custom;
@ -146,19 +146,6 @@ const showSuccessNotification = (title, message) => {
}; };
}; };
const showTempErrorNotification = (title, message) => {
return dispatch => {
dispatch(
showTempNotification({
level: 'error',
title,
message: message ? message : null,
autoDismiss: 3,
})
);
};
};
const showInfoNotification = title => { const showInfoNotification = title => {
return dispatch => { return dispatch => {
dispatch( dispatch(
@ -170,9 +157,42 @@ const showInfoNotification = title => {
}; };
}; };
const showWarningNotification = (title, message, dataObj) => {
const children = [];
if (dataObj) {
children.push(
<div className={styles.aceBlock}>
<AceEditor
readOnly
showPrintMargin={false}
mode="json"
showGutter={false}
theme="github"
name="notification-response"
value={JSON.stringify(dataObj, null, 4)}
minLines={1}
maxLines={15}
width="100%"
/>
</div>
);
}
return dispatch => {
dispatch(
showNotification({
level: 'warning',
title,
message,
children,
})
);
};
};
export { export {
showErrorNotification, showErrorNotification,
showSuccessNotification, showSuccessNotification,
showInfoNotification, showInfoNotification,
showTempErrorNotification, showWarningNotification,
}; };

View File

@ -136,7 +136,6 @@ class AddTable extends Component {
showErrorNotification( showErrorNotification(
'Error creating table!', 'Error creating table!',
'Minimum one column required', 'Minimum one column required',
'',
{ {
custom: ATLEAST_ONE_COLUMN_MSG, custom: ATLEAST_ONE_COLUMN_MSG,
} }
@ -155,7 +154,6 @@ class AddTable extends Component {
showErrorNotification( showErrorNotification(
'Error creating table!', 'Error creating table!',
'Column name cannot be empty', 'Column name cannot be empty',
'',
{ {
custom: 'Column name cannot be empty', custom: 'Column name cannot be empty',
} }
@ -167,7 +165,6 @@ class AddTable extends Component {
showErrorNotification( showErrorNotification(
gqlColumnErrorNotif[0], gqlColumnErrorNotif[0],
gqlColumnErrorNotif[1], gqlColumnErrorNotif[1],
gqlColumnErrorNotif[2],
gqlColumnErrorNotif[3] gqlColumnErrorNotif[3]
) )
); );
@ -192,7 +189,6 @@ class AddTable extends Component {
showErrorNotification( showErrorNotification(
gqlColumnErrorNotif[0], gqlColumnErrorNotif[0],
gqlColumnErrorNotif[1], gqlColumnErrorNotif[1],
gqlColumnErrorNotif[2],
gqlColumnErrorNotif[3] gqlColumnErrorNotif[3]
) )
); );
@ -214,7 +210,6 @@ class AddTable extends Component {
showErrorNotification( showErrorNotification(
'Error creating table!', 'Error creating table!',
'Select atleast one primary key', 'Select atleast one primary key',
'',
{ {
custom: ATLEAST_ONE_PRIMARY_KEY_MSG, custom: ATLEAST_ONE_PRIMARY_KEY_MSG,
} }
@ -233,7 +228,6 @@ class AddTable extends Component {
showErrorNotification( showErrorNotification(
'Error creating table!', 'Error creating table!',
'Table name cannot be empty', 'Table name cannot be empty',
'',
{ {
custom: 'Table name cannot be empty. Please add a name', custom: 'Table name cannot be empty. Please add a name',
} }
@ -245,7 +239,6 @@ class AddTable extends Component {
showErrorNotification( showErrorNotification(
gqlTableErrorNotif[0], gqlTableErrorNotif[0],
gqlTableErrorNotif[1], gqlTableErrorNotif[1],
gqlTableErrorNotif[2],
gqlTableErrorNotif[3] gqlTableErrorNotif[3]
) )
); );

View File

@ -435,34 +435,23 @@ const setTable = tableName => ({ type: SET_TABLE, tableName });
/* **********Shared functions between table actions********* */ /* **********Shared functions between table actions********* */
const handleMigrationErrors = (title, errorMsg) => dispatch => { const handleMigrationErrors = (title, errorMsg) => dispatch => {
const requestMsg = title;
if (globals.consoleMode === SERVER_CONSOLE_MODE) { if (globals.consoleMode === SERVER_CONSOLE_MODE) {
// handle errors for run_sql based workflow // handle errors for run_sql based workflow
dispatch(showErrorNotification(title, errorMsg.code, requestMsg, errorMsg)); dispatch(showErrorNotification(title, errorMsg.code, errorMsg));
} else if (errorMsg.code === 'migration_failed') { } else if (errorMsg.code === 'migration_failed') {
dispatch( dispatch(showErrorNotification(title, 'Migration Failed', errorMsg));
showErrorNotification(title, 'Migration Failed', requestMsg, errorMsg)
);
} else if (errorMsg.code === 'data_api_error') { } else if (errorMsg.code === 'data_api_error') {
const parsedErrorMsg = errorMsg; const parsedErrorMsg = errorMsg;
parsedErrorMsg.message = JSON.parse(errorMsg.message); parsedErrorMsg.message = JSON.parse(errorMsg.message);
dispatch( dispatch(
showErrorNotification( showErrorNotification(title, parsedErrorMsg.message.error, parsedErrorMsg)
title,
parsedErrorMsg.message.error,
requestMsg,
parsedErrorMsg
)
); );
} else { } else {
// any other unhandled codes // any other unhandled codes
const parsedErrorMsg = errorMsg; const parsedErrorMsg = errorMsg;
parsedErrorMsg.message = JSON.parse(errorMsg.message); parsedErrorMsg.message = JSON.parse(errorMsg.message);
dispatch( dispatch(showErrorNotification(title, errorMsg.code, parsedErrorMsg));
showErrorNotification(title, errorMsg.code, requestMsg, parsedErrorMsg)
);
} }
// dispatch(showErrorNotification(msg, firstDisplay, request, response));
}; };
const makeMigrationCall = ( const makeMigrationCall = (
@ -512,7 +501,7 @@ const makeMigrationCall = (
body: JSON.stringify(finalReqBody), body: JSON.stringify(finalReqBody),
}; };
const onSuccess = () => { const onSuccess = data => {
if (!shouldSkipSchemaReload) { if (!shouldSkipSchemaReload) {
if (globals.consoleMode === 'cli') { if (globals.consoleMode === 'cli') {
dispatch(loadMigrationStatus()); // don't call for server mode dispatch(loadMigrationStatus()); // don't call for server mode
@ -522,7 +511,7 @@ const makeMigrationCall = (
if (successMsg) { if (successMsg) {
dispatch(showSuccessNotification(successMsg)); dispatch(showSuccessNotification(successMsg));
} }
customOnSuccess(); customOnSuccess(data, globals.consoleMode, currMigrationMode);
}; };
const onError = err => { const onError = err => {
@ -600,7 +589,6 @@ const fetchColumnTypeInfo = () => {
showErrorNotification( showErrorNotification(
'Error fetching column types', 'Error fetching column types',
'Kindly reach out to us in case you face this issue again', 'Kindly reach out to us in case you face this issue again',
error,
error error
) )
); );

View File

@ -113,7 +113,6 @@ const executeSQL = (isMigration, migrationName) => (dispatch, getState) => {
showErrorNotification( showErrorNotification(
'SQL execution failed!', 'SQL execution failed!',
'Something is wrong. Data sent back an invalid response json.', 'Something is wrong. Data sent back an invalid response json.',
requestBody,
parsedErrorMsg parsedErrorMsg
) )
); );

View File

@ -13,7 +13,6 @@ export const createNewSchema = (schemaName, successCb, errorCb) => {
showErrorNotification( showErrorNotification(
gqlSchemaErrorNotif[0], gqlSchemaErrorNotif[0],
gqlSchemaErrorNotif[1], gqlSchemaErrorNotif[1],
gqlSchemaErrorNotif[2],
gqlSchemaErrorNotif[3] gqlSchemaErrorNotif[3]
) )
); );

View File

@ -95,9 +95,7 @@ const editItem = (tableName, colValues) => {
); );
}, },
err => { err => {
dispatch( dispatch(showErrorNotification('Edit failed!', err.error, err));
showErrorNotification('Edit failed!', err.error, reqBody, err)
);
} }
); );
}; };

View File

@ -195,9 +195,7 @@ const deleteItem = pkClause => {
); );
}, },
err => { err => {
dispatch( dispatch(showErrorNotification('Deleting row failed!', err.error, err));
showErrorNotification('Deleting row failed!', err.error, reqBody, err)
);
} }
); );
}; };

View File

@ -100,9 +100,7 @@ const insertItem = (tableName, colValues) => {
); );
}, },
err => { err => {
dispatch( dispatch(showErrorNotification('Insert failed!', err.error, err));
showErrorNotification('Insert failed!', err.error, reqBody, err)
);
} }
); );
}; };

View File

@ -38,7 +38,6 @@ const useColumnEditor = (dispatch, tableName) => {
showErrorNotification( showErrorNotification(
gqlColumnErrorNotif[0], gqlColumnErrorNotif[0],
gqlColumnErrorNotif[1], gqlColumnErrorNotif[1],
gqlColumnErrorNotif[2],
gqlColumnErrorNotif[3] gqlColumnErrorNotif[3]
) )
); );
@ -47,7 +46,6 @@ const useColumnEditor = (dispatch, tableName) => {
showErrorNotification( showErrorNotification(
'Error creating column!', 'Error creating column!',
'Column name/type cannot be empty', 'Column name/type cannot be empty',
'',
{ {
custom: 'Column name/type cannot be empty', custom: 'Column name/type cannot be empty',
} }

View File

@ -1,4 +1,4 @@
import React, { useEffect } from 'react'; import React from 'react';
import SearchableSelectBox from '../../../Common/SearchableSelect/SearchableSelect'; import SearchableSelectBox from '../../../Common/SearchableSelect/SearchableSelect';
import CustomInputAutoSuggest from '../../../Common/CustomInputAutoSuggest/CustomInputAutoSuggest'; import CustomInputAutoSuggest from '../../../Common/CustomInputAutoSuggest/CustomInputAutoSuggest';
@ -8,7 +8,6 @@ import { getValidAlterOptions } from './utils';
const ColumnEditor = ({ const ColumnEditor = ({
onSubmit, onSubmit,
dispatch, dispatch,
columnComment,
columnProperties, columnProperties,
selectedProperties, selectedProperties,
editColumn, editColumn,
@ -23,12 +22,6 @@ const ColumnEditor = ({
const styles = require('./ModifyTable.scss'); const styles = require('./ModifyTable.scss');
useEffect(() => {
if (columnComment) {
dispatch(editColumn(colName, 'comment', columnComment || ''));
}
}, [columnComment]);
const getColumnType = () => { const getColumnType = () => {
return ( return (
colName in selectedProperties && colName in selectedProperties &&
@ -78,7 +71,7 @@ const ColumnEditor = ({
dispatch(editColumn(colName, 'isUnique', e.target.value === 'true')); dispatch(editColumn(colName, 'isUnique', e.target.value === 'true'));
}; };
const getDefaultInput = () => { const getColumnDefaultInput = () => {
const theme = require('../../../Common/CustomInputAutoSuggest/CustomThemes/EditColumnDefault.scss'); const theme = require('../../../Common/CustomInputAutoSuggest/CustomThemes/EditColumnDefault.scss');
return ( return (
@ -156,19 +149,7 @@ const ColumnEditor = ({
</div> </div>
<div className={`${styles.display_flex} form-group`}> <div className={`${styles.display_flex} form-group`}>
<label className="col-xs-2">Default</label> <label className="col-xs-2">Default</label>
<div className="col-xs-6"> <div className="col-xs-6">{getColumnDefaultInput()}</div>
{getDefaultInput()}
{/*
<input
className="input-sm form-control"
value={selectedProperties[colName].default || ''}
onChange={updateColumnDef}
type="text"
disabled={columnProperties.pkConstraint}
data-test="edit-col-default"
/>
*/}
</div>
</div> </div>
<div className={`${styles.display_flex} form-group`}> <div className={`${styles.display_flex} form-group`}>
<label className="col-xs-2">Comment</label> <label className="col-xs-2">Comment</label>

View File

@ -71,16 +71,17 @@ const ColumnEditorList = ({
: false, : false,
// uniqueConstraint: columnUniqueConstraints[colName], // uniqueConstraint: columnUniqueConstraints[colName],
default: col.column_default || '', default: col.column_default || '',
comment: col.comment || '',
}; };
const onSubmit = () => { const onSubmit = toggleEditor => {
dispatch(saveColumnChangesSql(colName, col)); dispatch(saveColumnChangesSql(colName, col, toggleEditor));
}; };
const onDelete = () => { const onDelete = () => {
const isOk = confirm('Are you sure you want to delete?'); const isOk = confirm('Are you sure you want to delete?');
if (isOk) { if (isOk) {
dispatch(deleteColumnSql(tableName, colName, col)); dispatch(deleteColumnSql(col, tableSchema));
} }
}; };
@ -91,11 +92,13 @@ const ColumnEditorList = ({
} }
const isOk = window.confirm(confirmMessage); const isOk = window.confirm(confirmMessage);
if (isOk) { if (isOk) {
dispatch(deleteColumnSql(tableName, colName, col)); dispatch(deleteColumnSql(col, tableSchema));
} }
}; };
const keyProperties = () => { const keyProperties = () => {
const propertiesDisplay = [];
const propertiesList = []; const propertiesList = [];
propertiesList.push(columnProperties.display_type_name); propertiesList.push(columnProperties.display_type_name);
@ -118,7 +121,17 @@ const ColumnEditorList = ({
const keyPropertiesString = propertiesList.join(', '); const keyPropertiesString = propertiesList.join(', ');
return <i>{keyPropertiesString && `- ${keyPropertiesString}`}</i>; propertiesDisplay.push(
<i key={'props'}>{keyPropertiesString && `- ${keyPropertiesString}`}</i>
);
propertiesDisplay.push(<br />);
propertiesDisplay.push(
<span key={'comment'} className={styles.text_gray}>
{columnProperties.comment && `${columnProperties.comment}`}
</span>
);
return propertiesDisplay;
}; };
const collapsedLabel = () => { const collapsedLabel = () => {
@ -192,7 +205,6 @@ const ColumnEditorList = ({
tableName={tableName} tableName={tableName}
dispatch={dispatch} dispatch={dispatch}
currentSchema={currentSchema} currentSchema={currentSchema}
columnComment={col.comment}
columnProperties={columnProperties} columnProperties={columnProperties}
selectedProperties={columnEdit} selectedProperties={columnEdit}
editColumn={editColumn} editColumn={editColumn}

View File

@ -11,6 +11,7 @@ import { SET_SQL } from '../RawSQL/Actions';
import { import {
showErrorNotification, showErrorNotification,
showSuccessNotification, showSuccessNotification,
showWarningNotification,
} from '../../Common/Notification'; } from '../../Common/Notification';
import dataHeaders from '../Common/Headers'; import dataHeaders from '../Common/Headers';
import { UPDATE_MIGRATION_STATUS_ERROR } from '../../../Main/Actions'; import { UPDATE_MIGRATION_STATUS_ERROR } from '../../../Main/Actions';
@ -497,7 +498,6 @@ const changeTableOrViewName = (isTable, oldName, newName) => {
showErrorNotification( showErrorNotification(
gqlValidationError[4], gqlValidationError[4],
gqlValidationError[1], gqlValidationError[1],
gqlValidationError[2],
gqlValidationError[3] gqlValidationError[3]
) )
); );
@ -750,12 +750,7 @@ const fetchViewDefinition = (viewName, isRedirect) => {
}, },
err => { err => {
dispatch( dispatch(
showErrorNotification( showErrorNotification('Fetching definition failed!', err.error, err)
'Fetching definition failed!',
err.error,
reqBody,
err
)
); );
} }
); );
@ -808,61 +803,191 @@ const deleteViewSql = viewName => {
}; };
}; };
const deleteColumnSql = (tableName, colName) => { const deleteColumnSql = (column, tableSchema) => {
return (dispatch, getState) => { return (dispatch, getState) => {
const currentSchema = getState().tables.currentSchema; const name = column.column_name;
const deleteQueryUp = const tableName = column.table_name;
'ALTER TABLE ' + const currentSchema = column.table_schema;
'"' + const comment = column.comment;
currentSchema + const is_nullable = column.is_nullable;
'"' + const col_type = column.udt_name;
'.' + const foreign_key_constraints = tableSchema.foreign_key_constraints.filter(
'"' + fkc => {
tableName + const columnKeys = Object.keys(fkc.column_mapping);
'"' + return columnKeys.includes(name);
' DROP COLUMN ' + }
'"' + );
colName + const opp_foreign_key_constraints = tableSchema.opp_foreign_key_constraints.filter(
'"'; fkc => {
const columnKeys = Object.values(fkc.column_mapping);
return columnKeys.includes(name);
}
);
const unique_constraints = tableSchema.unique_constraints.filter(uc =>
uc.columns.includes(name)
);
const alterStatement =
'ALTER TABLE ' + '"' + currentSchema + '"' + '.' + '"' + tableName + '" ';
const schemaChangesUp = [ const schemaChangesUp = [
{ {
type: 'run_sql', type: 'run_sql',
args: { args: {
sql: deleteQueryUp, sql: alterStatement + 'DROP COLUMN ' + '"' + name + '" CASCADE',
}, },
}, },
]; ];
const schemaChangesDown = [];
/* schemaChangesDown.push({
const schemaChangesDown = [{
type: 'run_sql', type: 'run_sql',
args: { args: {
'sql': deleteQueryDown sql: alterStatement + 'ADD COLUMN ' + '"' + name + '"' + ' ' + col_type,
} },
}]; });
*/
if (is_nullable) {
schemaChangesDown.push({
type: 'run_sql',
args: {
sql:
alterStatement +
'ALTER COLUMN ' +
'"' +
name +
'" ' +
'DROP NOT NULL',
},
});
} else {
schemaChangesDown.push({
type: 'run_sql',
args: {
sql:
alterStatement +
'ALTER COLUMN ' +
'"' +
name +
'" ' +
'SET NOT NULL',
},
});
}
const merged_fkc = foreign_key_constraints.concat(opp_foreign_key_constraints);
if (merged_fkc.length > 0) {
merged_fkc.forEach(fkc => {
// add foreign key constraint to down migration
const lcol = Object.keys(fkc.column_mapping);
const rcol = Object.values(fkc.column_mapping);
const onUpdate = pgConfTypes[fkc.on_update];
const onDelete = pgConfTypes[fkc.on_delete];
schemaChangesDown.push({
type: 'run_sql',
args: {
sql:
alterStatement +
'ADD CONSTRAINT ' +
`${fkc.constraint_name} ` +
'FOREIGN KEY ' +
`(${lcol.join(', ')}) ` +
'REFERENCES ' +
`"${fkc.ref_table_table_schema}"."${fkc.ref_table}" ` +
`(${rcol.join(', ')}) ` +
`ON DELETE ${onDelete} ` +
`ON UPDATE ${onUpdate}`,
},
});
});
}
if (unique_constraints.length > 0) {
unique_constraints.forEach(uc => {
// add unique constraint to down migration
schemaChangesDown.push({
type: 'run_sql',
args: {
sql:
alterStatement +
'ADD CONSTRAINT ' +
`${uc.constraint_name} ` +
'UNIQUE ' +
`(${uc.columns.join(', ')})`,
},
});
});
}
if (column.column_default !== null) {
// add column default to down migration
schemaChangesDown.push({
type: 'run_sql',
args: {
sql:
alterStatement +
'ALTER COLUMN ' +
`"${name}" ` +
'SET DEFAULT ' +
column.column_default,
},
});
}
// COMMENT ON COLUMN my_table.my_column IS 'Employee ID number';
if (comment) {
schemaChangesDown.push({
type: 'run_sql',
args: {
sql:
'COMMENT ON COLUMN ' +
'"' +
currentSchema +
'"' +
'.' +
'"' +
tableName +
'"' +
'.' +
'"' +
name +
'"' +
' ' +
'IS ' +
"'" +
comment +
"'",
},
});
}
// Apply migrations // Apply migrations
const migrationName = const migrationName =
'alter_table_' + 'alter_table_' + currentSchema + '_' + tableName + '_drop_column_' + name;
currentSchema +
'_' +
tableName +
'_drop_column_' +
colName;
const requestMsg = 'Deleting Column...'; const requestMsg = 'Deleting Column...';
const successMsg = 'Column deleted'; const successMsg = 'Column deleted';
const errorMsg = 'Deleting column failed'; const errorMsg = 'Deleting column failed';
const customOnSuccess = () => {}; const customOnSuccess = (data, consoleMode, migrationMode) => {
if (consoleMode === 'cli' && migrationMode) {
// show warning information
dispatch(
showWarningNotification(
'Check down migration',
'Please verify that the down migration will reset the DB to the previous state (you ' +
'might need to add recreation of some dependent objects like indexes, etc.)',
data
)
);
}
};
const customOnError = () => {}; const customOnError = () => {};
makeMigrationCall( makeMigrationCall(
dispatch, dispatch,
getState, getState,
schemaChangesUp, schemaChangesUp,
[], schemaChangesDown,
migrationName, migrationName,
customOnSuccess, customOnSuccess,
customOnError, customOnError,
@ -1159,7 +1284,7 @@ const isColumnUnique = (tableSchema, colName) => {
); );
}; };
const saveColumnChangesSql = (colName, column) => { const saveColumnChangesSql = (colName, column, onSuccess) => {
// eslint-disable-line no-unused-vars // eslint-disable-line no-unused-vars
return (dispatch, getState) => { return (dispatch, getState) => {
const columnEdit = getState().tables.modify.columnEdit[colName]; const columnEdit = getState().tables.modify.columnEdit[colName];
@ -1663,7 +1788,6 @@ const saveColumnChangesSql = (colName, column) => {
showErrorNotification( showErrorNotification(
gqlColumnErrorNotif[4], gqlColumnErrorNotif[4],
gqlColumnErrorNotif[1], gqlColumnErrorNotif[1],
gqlColumnErrorNotif[2],
gqlColumnErrorNotif[3] gqlColumnErrorNotif[3]
) )
); );
@ -1696,7 +1820,8 @@ const saveColumnChangesSql = (colName, column) => {
const errorMsg = 'Modifying column failed'; const errorMsg = 'Modifying column failed';
const customOnSuccess = () => { const customOnSuccess = () => {
dispatch(setColumnEdit(columnEdit)); dispatch(resetColumnEdit(colName));
onSuccess();
}; };
const customOnError = () => {}; const customOnError = () => {};
@ -1750,7 +1875,6 @@ const fetchColumnCasts = () => {
showErrorNotification( showErrorNotification(
'Error fetching column casts information', 'Error fetching column casts information',
'Kindly reach out to us in case you face this issue again', 'Kindly reach out to us in case you face this issue again',
error,
error error
) )
); );

View File

@ -371,7 +371,6 @@ const addRelViewMigrate = (tableSchema, toggleEditor) => (
showErrorNotification( showErrorNotification(
'Error adding relationship!', 'Error adding relationship!',
'Please select a name for the relationship', 'Please select a name for the relationship',
'',
{ custom: 'Relationship name cannot be empty' } { custom: 'Relationship name cannot be empty' }
) )
); );
@ -380,7 +379,6 @@ const addRelViewMigrate = (tableSchema, toggleEditor) => (
showErrorNotification( showErrorNotification(
gqlRelErrorNotif[0], gqlRelErrorNotif[0],
gqlRelErrorNotif[1], gqlRelErrorNotif[1],
gqlRelErrorNotif[2],
gqlRelErrorNotif[3] gqlRelErrorNotif[3]
) )
); );

View File

@ -52,7 +52,6 @@ class RelationshipEditor extends React.Component {
showErrorNotification( showErrorNotification(
gqlRelErrorNotif[4], gqlRelErrorNotif[4],
gqlRelErrorNotif[1], gqlRelErrorNotif[1],
gqlRelErrorNotif[2],
gqlRelErrorNotif[3] gqlRelErrorNotif[3]
) )
); );

View File

@ -52,7 +52,6 @@ const addRelationshipCellView = (
showErrorNotification( showErrorNotification(
'Error adding relationship!', 'Error adding relationship!',
'Please select a name for the relationship', 'Please select a name for the relationship',
'',
{ custom: 'Relationship name cannot be empty' } { custom: 'Relationship name cannot be empty' }
) )
); );
@ -62,7 +61,6 @@ const addRelationshipCellView = (
showErrorNotification( showErrorNotification(
gqlRelErrorNotif[0], gqlRelErrorNotif[0],
gqlRelErrorNotif[1], gqlRelErrorNotif[1],
gqlRelErrorNotif[2],
gqlRelErrorNotif[3] gqlRelErrorNotif[3]
) )
); );

View File

@ -1,7 +1,7 @@
import defaultState from './AddState'; import defaultState from './AddState';
import _push from '../push'; import _push from '../push';
import { loadTriggers, makeMigrationCall, setTrigger } from '../EventActions'; import { loadTriggers, makeMigrationCall, setTrigger } from '../EventActions';
import { showSuccessNotification } from '../Notification'; import { showSuccessNotification } from '../../Common/Notification';
import { UPDATE_MIGRATION_STATUS_ERROR } from '../../../Main/Actions'; import { UPDATE_MIGRATION_STATUS_ERROR } from '../../../Main/Actions';
import { updateSchemaInfo } from '../../Data/DataActions'; import { updateSchemaInfo } from '../../Data/DataActions';

View File

@ -27,7 +27,7 @@ import {
loadTableList, loadTableList,
} from './AddActions'; } from './AddActions';
import { listDuplicate } from '../../../../utils/data'; import { listDuplicate } from '../../../../utils/data';
import { showErrorNotification } from '../Notification'; import { showErrorNotification } from '../../Common/Notification';
import { createTrigger } from './AddActions'; import { createTrigger } from './AddActions';
import DropdownButton from '../../../Common/DropdownButton/DropdownButton'; import DropdownButton from '../../../Common/DropdownButton/DropdownButton';
@ -146,7 +146,7 @@ class AddTrigger extends Component {
this.props.dispatch(createTrigger()); this.props.dispatch(createTrigger());
} else { } else {
this.props.dispatch( this.props.dispatch(
showErrorNotification('Error creating trigger!', errorMsg, '', { showErrorNotification('Error creating trigger!', errorMsg, {
custom: customMsg, custom: customMsg,
}) })
); );

View File

@ -5,7 +5,10 @@ import processedEventsReducer from './ProcessedEvents/ViewActions';
import pendingEventsReducer from './PendingEvents/ViewActions'; import pendingEventsReducer from './PendingEvents/ViewActions';
import runningEventsReducer from './RunningEvents/ViewActions'; import runningEventsReducer from './RunningEvents/ViewActions';
import streamingLogsReducer from './StreamingLogs/LogActions'; import streamingLogsReducer from './StreamingLogs/LogActions';
import { showErrorNotification, showSuccessNotification } from './Notification'; import {
showSuccessNotification,
showErrorNotification,
} from '../Common/Notification';
import dataHeaders from './Common/Headers'; import dataHeaders from './Common/Headers';
import { loadMigrationStatus } from '../../Main/Actions'; import { loadMigrationStatus } from '../../Main/Actions';
import returnMigrateUrl from './Common/getMigrateUrl'; import returnMigrateUrl from './Common/getMigrateUrl';
@ -317,34 +320,23 @@ const setRedeliverEvent = eventId => dispatch => {
/* **********Shared functions between table actions********* */ /* **********Shared functions between table actions********* */
const handleMigrationErrors = (title, errorMsg) => dispatch => { const handleMigrationErrors = (title, errorMsg) => dispatch => {
const requestMsg = title;
if (globals.consoleMode === SERVER_CONSOLE_MODE) { if (globals.consoleMode === SERVER_CONSOLE_MODE) {
// handle errors for run_sql based workflow // handle errors for run_sql based workflow
dispatch(showErrorNotification(title, errorMsg.code, requestMsg, errorMsg)); dispatch(showErrorNotification(title, errorMsg.code, errorMsg));
} else if (errorMsg.code === 'migration_failed') { } else if (errorMsg.code === 'migration_failed') {
dispatch( dispatch(showErrorNotification(title, 'Migration Failed', errorMsg));
showErrorNotification(title, 'Migration Failed', requestMsg, errorMsg)
);
} else if (errorMsg.code === 'data_api_error') { } else if (errorMsg.code === 'data_api_error') {
const parsedErrorMsg = errorMsg; const parsedErrorMsg = errorMsg;
parsedErrorMsg.message = JSON.parse(errorMsg.message); parsedErrorMsg.message = JSON.parse(errorMsg.message);
dispatch( dispatch(
showErrorNotification( showErrorNotification(title, parsedErrorMsg.message.error, parsedErrorMsg)
title,
parsedErrorMsg.message.error,
requestMsg,
parsedErrorMsg
)
); );
} else { } else {
// any other unhandled codes // any other unhandled codes
const parsedErrorMsg = errorMsg; const parsedErrorMsg = errorMsg;
parsedErrorMsg.message = JSON.parse(errorMsg.message); parsedErrorMsg.message = JSON.parse(errorMsg.message);
dispatch( dispatch(showErrorNotification(title, errorMsg.code, parsedErrorMsg));
showErrorNotification(title, errorMsg.code, requestMsg, parsedErrorMsg)
);
} }
// dispatch(showErrorNotification(msg, firstDisplay, request, response));
}; };
const makeMigrationCall = ( const makeMigrationCall = (

View File

@ -1,7 +1,7 @@
import defaultState from './State'; import defaultState from './State';
import { loadTriggers, makeMigrationCall, setTrigger } from '../EventActions'; import { loadTriggers, makeMigrationCall, setTrigger } from '../EventActions';
import { UPDATE_MIGRATION_STATUS_ERROR } from '../../../Main/Actions'; import { UPDATE_MIGRATION_STATUS_ERROR } from '../../../Main/Actions';
import { showErrorNotification } from '../Notification'; import { showErrorNotification } from '../../Common/Notification';
import { MANUAL_TRIGGER_VAR } from './utils'; import { MANUAL_TRIGGER_VAR } from './utils';
@ -70,7 +70,7 @@ export const REQUEST_COMPLETE = 'ModifyTrigger/REQUEST_COMPLETE';
export const showValidationError = message => { export const showValidationError = message => {
return dispatch => { return dispatch => {
dispatch( dispatch(
showErrorNotification('Error modifying trigger!', 'Invalid input', '', { showErrorNotification('Error modifying trigger!', 'Invalid input', {
custom: message, custom: message,
}) })
); );

View File

@ -1,178 +0,0 @@
import React from 'react';
import AceEditor from 'react-ace';
import { showNotification, showTempNotification } from '../../App/Actions';
import { notifExpand, notifMsg } from '../../App/Actions';
import Button from '../../Common/Button/Button';
const styles = require('../../Common/TableCommon/Table.scss');
const showErrorNotification = (title, message, reqBody, error) => {
let modMessage;
let refreshBtn;
if (
error &&
error.message &&
(error.message.error === 'postgres query error' ||
error.message.error === 'query execution failed')
) {
if (error.message.internal) {
modMessage =
error.message.code + ': ' + error.message.internal.error.message;
} else {
modMessage = error.code + ': ' + error.message.error;
}
} else if (error && 'info' in error) {
modMessage = error.info;
} else if (error && 'message' in error) {
if (error.code) {
if (error.message.error) {
modMessage = error.message.error.message;
} else {
modMessage = error.message;
}
} else if (error && error.message && 'code' in error.message) {
modMessage = error.message.code + ' : ' + message;
} else {
modMessage = error.code;
}
} else if (error && 'internal' in error) {
modMessage = error.code + ' : ' + error.internal.error.message;
} else if (error && 'custom' in error) {
modMessage = error.custom;
} else if (error && 'code' in error && 'error' in error && 'path' in error) {
// Data API error
modMessage = error.error;
} else {
modMessage = error ? error : message;
}
let finalJson = error ? error.message : '{}';
if (error && 'action' in error) {
refreshBtn = (
<Button
className={styles.add_mar_top_small}
color="yellow"
size="sm"
onClick={e => {
e.preventDefault();
window.location.reload();
}}
>
Refresh Console
</Button>
);
finalJson = error.action;
} else if (error && 'internal' in error) {
finalJson = error.internal;
}
return dispatch => {
const expandClicked = finalMsg => {
// trigger a modal with a bigger view
dispatch(notifExpand(true));
dispatch(notifMsg(JSON.stringify(finalMsg, null, 4)));
};
const getNotificationAction = () => {
let action = null;
if (reqBody) {
const notification = [
<div className={styles.aceBlock}>
<i
onClick={e => {
e.preventDefault();
expandClicked(finalJson);
}}
className={styles.aceBlockExpand + ' fa fa-expand'}
/>
<AceEditor
readOnly
showPrintMargin={false}
mode="json"
showGutter={false}
theme="github"
name="notification-response"
value={JSON.stringify(finalJson, null, 4)}
minLines={1}
maxLines={15}
width="100%"
/>
{refreshBtn}
</div>,
];
action = {
label: 'Details',
callback: () => {
dispatch(
showNotification({
level: 'error',
title,
message: modMessage,
dismissible: 'button',
children: notification,
})
);
},
};
}
return action;
};
dispatch(
showNotification({
level: 'error',
title,
message: modMessage,
action: getNotificationAction(),
})
);
};
};
const showSuccessNotification = (title, message) => {
return dispatch => {
dispatch(
showNotification({
level: 'success',
title,
message: message ? message : null,
})
);
};
};
const showTempErrorNotification = (title, message) => {
return dispatch => {
dispatch(
showTempNotification({
level: 'error',
title,
message: message ? message : null,
autoDismiss: 3,
})
);
};
};
const showInfoNotification = title => {
return dispatch => {
dispatch(
showNotification({
title,
autoDismiss: 0,
})
);
};
};
export {
showErrorNotification,
showSuccessNotification,
showInfoNotification,
showTempErrorNotification,
};

View File

@ -6,7 +6,7 @@ import { findTableFromRel } from '../utils';
import { import {
showSuccessNotification, showSuccessNotification,
showErrorNotification, showErrorNotification,
} from '../Notification'; } from '../../Common/Notification';
import dataHeaders from '../Common/Headers'; import dataHeaders from '../Common/Headers';
/* ****************** View actions *************/ /* ****************** View actions *************/
@ -192,9 +192,7 @@ const deleteItem = pkClause => {
); );
}, },
err => { err => {
dispatch( dispatch(showErrorNotification('Deleting row failed!', err.error, err));
showErrorNotification('Deleting row failed!', err.error, reqBody, err)
);
} }
); );
}; };

View File

@ -306,7 +306,6 @@ export const addAllowedQueries = (queries, isEmptyList, callback) => {
showErrorNotification( showErrorNotification(
'Adding query to allow-list failed', 'Adding query to allow-list failed',
null, null,
null,
error error
) )
); );
@ -338,7 +337,6 @@ export const deleteAllowList = () => {
showErrorNotification( showErrorNotification(
'Deleting queries from allow-list failed', 'Deleting queries from allow-list failed',
null, null,
null,
error error
) )
); );
@ -372,7 +370,6 @@ export const deleteAllowedQuery = (queryName, isLastQuery) => {
showErrorNotification( showErrorNotification(
'Deleting query from allow-list failed', 'Deleting query from allow-list failed',
null, null,
null,
error error
) )
); );
@ -399,12 +396,7 @@ export const updateAllowedQuery = (queryName, newQuery) => {
error => { error => {
console.error(error); console.error(error);
dispatch( dispatch(
showErrorNotification( showErrorNotification('Updating allow-list query failed', null, error)
'Updating allow-list query failed',
null,
null,
error
)
); );
} }
); );

View File

@ -63,7 +63,6 @@ class ExportMetadata extends Component {
showErrorNotification( showErrorNotification(
'Metadata export failed', 'Metadata export failed',
'Something is wrong.', 'Something is wrong.',
requestBody,
parsedErrorMsg parsedErrorMsg
) )
); );

View File

@ -63,7 +63,6 @@ class ImportMetadata extends Component {
showErrorNotification( showErrorNotification(
'Metadata import failed', 'Metadata import failed',
'Something is wrong.', 'Something is wrong.',
requestBody,
parsedErrorMsg parsedErrorMsg
) )
); );

View File

@ -66,7 +66,6 @@ class ResetMetadata extends Component {
showErrorNotification( showErrorNotification(
'Metadata reset failed', 'Metadata reset failed',
'Something went wrong.', 'Something went wrong.',
requestBody,
parsedErrorMsg parsedErrorMsg
) )
); );