Skip to content
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

add computed fields support on console #3522

Merged
merged 36 commits into from
Jan 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
208dd44
add computed fields support on console <WIP>
rikinsk Dec 12, 2019
8cc5387
handle local state
rikinsk Dec 13, 2019
c111cf8
Merge branch 'master' into console-computed-fields
rikinsk Dec 17, 2019
7731790
Merge branch 'master' into console-computed-fields
rikinsk Dec 17, 2019
f7a39af
fix computed fields local state
rikinsk Dec 17, 2019
2eeabb1
add computed fields api calls
rikinsk Dec 17, 2019
80e077b
Merge branch 'console-computed-fields' of github.com:rikinsk/graphql-…
rikinsk Dec 18, 2019
122455e
track and relate hdb_computed_field_function
rikinsk Dec 18, 2019
abdd967
Merge branch 'master' into console-computed-fields
rikinsk Dec 18, 2019
574248f
fix bug
rikinsk Dec 18, 2019
713126b
refresh function lists in Modify table for computed fields
rikinsk Dec 18, 2019
edd4bbc
fix local state after delete
rikinsk Dec 18, 2019
cb3b5d0
Add empty SQL migration for metadata changes
lexi-lambda Dec 18, 2019
7ebd1fe
handle computed field comment
rikinsk Dec 19, 2019
e415b2f
Merge branch 'console-computed-fields' of github.com:rikinsk/graphql-…
rikinsk Dec 19, 2019
3bfda4b
Merge branch 'master' into console-computed-fields
rikinsk Dec 23, 2019
0c14c52
track and relate hdb_computed_field
rikinsk Dec 23, 2019
357f6e0
update computed field format
rikinsk Dec 23, 2019
e4cf1da
make fn selection dropdown
rikinsk Dec 24, 2019
44cdf92
Merge branch 'master' into console-computed-fields
rikinsk Dec 26, 2019
a20a432
add computed field console flow to docs
rikinsk Dec 26, 2019
9246e49
metadata api -> api
rikinsk Dec 26, 2019
57122fc
Merge branch 'master' into console-computed-fields
rikinsk Dec 30, 2019
9d32f22
add version support note to docs and tool tip for table row argument
rikinsk Dec 30, 2019
c87de89
Merge branch 'master' into console-computed-fields
rikinsk Dec 30, 2019
f679779
update col preset tooltip
rikinsk Jan 8, 2020
b33101b
Merge branch 'master' into console-computed-fields
rikinsk Jan 8, 2020
2b59068
allow nested-ternary
rikinsk Jan 8, 2020
a0f7237
move queries
rikinsk Jan 8, 2020
7e22627
add trackable functions view button
rikinsk Jan 9, 2020
b5085f9
make function name searchable
rikinsk Jan 9, 2020
d2dae3c
add permissions
rikinsk Jan 9, 2020
b7e6c86
Merge branch 'console-functions' into console-computed-fields
rikinsk Jan 9, 2020
f1ab375
Merge branch 'master' into console-computed-fields
rikinsk Jan 10, 2020
0028190
update docs
rikinsk Jan 10, 2020
1f544d9
Merge branch 'master' into console-computed-fields
rikinsk Jan 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion console/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@
"jsx-a11y/alt-text": 0,
"jsx-a11y/no-autofocus": 0,
"max-len": 0,
"no-continue": 0
"no-continue": 0,
"no-nested-ternary": 0
},
"plugins": [
"react", "import", "cypress"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Select, { components, createFilter } from 'react-select';
import PropTypes from 'prop-types';
import { isArray, isObject } from '../utils/jsUtils';

/*
* Wrap the option generated by react-select and adds utility properties
Expand Down Expand Up @@ -64,6 +65,17 @@ const SearchableSelectBox = ({
customFilter = {};
}

// handle simple options
if (isArray(options) && !isObject(options[0])) {
options = options.map(op => {
return { value: op, label: op };
});
}

if (value && !isObject(value)) {
value = { value: value, label: value };
}

return (
<Select
isSearchable
Expand Down
47 changes: 47 additions & 0 deletions console/src/components/Common/utils/pgUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,22 @@ export const getFunctionName = pgFunction => {
return pgFunction.function_name;
};

export const getFunctionDefinition = pgFunction => {
return pgFunction.function_definition;
};

export const getSchemaFunctions = (allFunctions, fnSchema) => {
return allFunctions.filter(fn => getFunctionSchema(fn) === fnSchema);
};

export const findFunction = (allFunctions, functionName, functionSchema) => {
return allFunctions.find(
f =>
getFunctionName(f) === functionName &&
getFunctionSchema(f) === functionSchema
);
};

/*** Schema utils ***/

export const getSchemaName = schema => {
Expand Down Expand Up @@ -264,3 +280,34 @@ export const getTableCustomColumnNames = table => {
}
return {};
};

/*** Table/View Computed Field utils ***/

export const getTableComputedFields = table => {
return table.computed_fields;
};

export const getComputedFieldName = computedField => {
return computedField.computed_field_name;
};

export const getGroupedTableComputedFields = (table, allFunctions) => {
const groupedComputedFields = { scalar: [], table: [] };

getTableComputedFields(table).forEach(computedField => {
const computedFieldFnDef = computedField.definition.function;
const computedFieldFn = findFunction(
allFunctions,
computedFieldFnDef.name,
computedFieldFnDef.schema
);

if (computedFieldFn && computedFieldFn.return_type_type === 'b') {
groupedComputedFields.scalar.push(computedField);
} else {
groupedComputedFields.table.push(computedField);
}
});

return groupedComputedFields;
};
29 changes: 29 additions & 0 deletions console/src/components/Common/utils/v1QueryUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,32 @@ export const getUntrackTableQuery = tableDef => {
},
};
};

export const getAddComputedFieldQuery = (
tableDef,
computedFieldName,
definition,
comment
) => {
return {
type: 'add_computed_field',
args: {
table: tableDef,
name: computedFieldName,
definition: {
...definition,
},
comment: comment,
},
};
};

export const getDropComputedFieldQuery = (tableDef, computedFieldName) => {
return {
type: 'drop_computed_field',
args: {
table: tableDef,
name: computedFieldName,
},
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import _push from '../../push';
import { SET_SQL } from '../../RawSQL/Actions';
import Button from '../../../../Common/Button/Button';

const RawSqlButton = props => {
const { dataTestId, sql, customStyles, dispatch, children } = props;

const handleClick = e => {
e.preventDefault();

dispatch(_push('/data/sql'));

dispatch({
type: SET_SQL,
data: sql,
});
};

return (
<Button
data-test={dataTestId}
className={`${customStyles} btn btn-xs btn-default`}
onClick={handleClick}
>
{children}
</Button>
);
};

export default RawSqlButton;
12 changes: 7 additions & 5 deletions console/src/components/Services/Data/DataActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ const initQueries = {
has_variadic: false,
returns_set: true,
return_type_type: 'c', // COMPOSITE type
return_table_info: {},
$or: [
{
function_type: {
Expand Down Expand Up @@ -168,6 +169,7 @@ const initQueries = {
has_variadic: false,
returns_set: true,
return_type_type: 'c', // COMPOSITE type
return_table_info: {},
$or: [
{
function_type: {
Expand Down Expand Up @@ -372,7 +374,7 @@ const fetchDataInit = () => (dispatch, getState) => {
);
};

const fetchFunctionInit = () => (dispatch, getState) => {
const fetchFunctionInit = (schema = null) => (dispatch, getState) => {
const url = Endpoints.getSchema;
const body = {
type: 'bulk',
Expand All @@ -384,10 +386,10 @@ const fetchFunctionInit = () => (dispatch, getState) => {
};

// set schema in queries
const currentSchema = getState().tables.currentSchema;
body.args[0].args.where.function_schema = currentSchema;
body.args[1].args.where.function_schema = currentSchema;
body.args[2].args.where.function_schema = currentSchema;
const fnSchema = schema || getState().tables.currentSchema;
body.args[0].args.where.function_schema = fnSchema;
body.args[1].args.where.function_schema = fnSchema;
body.args[2].args.where.function_schema = fnSchema;

const options = {
credentials: globalCookiePolicy,
Expand Down
1 change: 1 addition & 0 deletions console/src/components/Services/Data/DataState.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const defaultQueryPermissions = {
},
select: {
columns: [],
computed_fields: [],
filter: {},
limit: null,
allow_aggregations: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,9 @@ class PermissionsSummary extends Component {
<div className={styles.add_mar_bottom_small}>
<b>Columns</b> -{' '}
<i>
{getPermissionColumnAccessSummary(
actionPermission,
table.columns
)}
{getPermissionColumnAccessSummary(actionPermission, {
columns: table.columns,
})}
</i>
{showDetails && getColumnsDetails()}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,31 @@ export const getPermissionFilterString = (
return filterString;
};

export const getPermissionColumnAccessSummary = (permission, tableColumns) => {
export const getPermissionColumnAccessSummary = (permission, tableFields) => {
let columnAccessStatus;

if (!permission || !permission.columns.length) {
if (!permission) {
columnAccessStatus = 'no columns';
} else if (
permission.columns === '*' ||
permission.columns.length === tableColumns.length
) {
columnAccessStatus = 'all columns';
} else {
columnAccessStatus = 'partial columns';
let noFields = true;
let allFields = true;

Object.keys(tableFields).forEach(fieldType => {
noFields = noFields && !permission[fieldType].length;

allFields =
allFields &&
(permission[fieldType] === '*' ||
permission[fieldType].length === tableFields[fieldType].length);
});

if (noFields) {
columnAccessStatus = 'no columns';
} else if (allFields) {
columnAccessStatus = 'all columns';
} else {
columnAccessStatus = 'partial columns';
}
}

return columnAccessStatus;
Expand Down
9 changes: 5 additions & 4 deletions console/src/components/Services/Data/RawSQL/RawSQL.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ const RawSQL = ({
// set SQL from localStorage on mount and write back to localStorage on unmount
useEffect(() => {
const LS_RAW_SQL_SQL = 'rawSql:sql';

const sqlFromLocalStorage = localStorage.getItem(LS_RAW_SQL_SQL);
if (sqlFromLocalStorage) {
dispatch({ type: SET_SQL, data: sqlFromLocalStorage });
if (!sql) {
const sqlFromLocalStorage = localStorage.getItem(LS_RAW_SQL_SQL);
if (sqlFromLocalStorage) {
dispatch({ type: SET_SQL, data: sqlFromLocalStorage });
}
}

return () => {
Expand Down
56 changes: 27 additions & 29 deletions console/src/components/Services/Data/Schema/Schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@ import {
getSchemaTables,
getUntrackedTables,
} from '../../../Common/utils/pgUtils';
import { SET_SQL } from '../RawSQL/Actions';
import _push from '../push';
import { isEmpty } from '../../../Common/utils/jsUtils';
import { getConfirmation } from '../../../Common/utils/jsUtils';
import ToolTip from '../../../Common/Tooltip/Tooltip';
import KnowMoreLink from '../../../Common/KnowMoreLink/KnowMoreLink';
import RawSqlButton from '../Common/ReusableComponents/RawSqlButton';

class Schema extends Component {
constructor(props) {
Expand Down Expand Up @@ -83,13 +82,9 @@ class Schema extends Component {
const trackedFuncNames = trackedFunctions.map(fn => getFunctionName(fn));

// Assuming schema for both function and tables are same
// return function which are tracked && function name whose
// set of tables are tracked
// return function which are tracked
const filterCondition = func => {
return (
!trackedFuncNames.includes(getFunctionName(func)) &&
!!func.return_table_info
);
return !trackedFuncNames.includes(getFunctionName(func));
};

return functionsList.filter(filterCondition);
Expand Down Expand Up @@ -454,7 +449,6 @@ class Schema extends Component {
if (isEmpty(untrackedRelations)) {
untrackedRelList.push(
<div key="no-untracked-rel">There are no untracked relations</div>
.ne
);
} else {
untrackedRelations.forEach((rel, i) => {
Expand Down Expand Up @@ -557,9 +551,7 @@ class Schema extends Component {
};

return (
<div
className={`${styles.display_inline} ${styles.add_mar_right}`}
>
<div className={styles.display_inline}>
<Button
data-test={`add-track-function-${p.function_name}`}
className={`${
Expand All @@ -579,7 +571,23 @@ class Schema extends Component {
key={`untracked-function-${i}`}
>
{getTrackBtn()}
<div className={styles.display_inline}>
<div
className={`${styles.display_inline} ${
styles.add_mar_left_mid
}`}
>
<RawSqlButton
dataTestId={`view-function-${p.function_name}`}
customStyles={styles.display_inline}
sql={p.function_definition}
dispatch={dispatch}
>
View
</RawSqlButton>
</div>
<div
className={`${styles.display_inline} ${styles.add_mar_left}`}
>
<span>{p.function_name}</span>
</div>
</div>
Expand Down Expand Up @@ -634,24 +642,14 @@ class Schema extends Component {
<div
className={`${styles.display_inline} ${styles.add_mar_right}`}
>
<Button
data-test={`view-function-${p.function_name}`}
className={`${
styles.display_inline
} btn btn-xs btn-default`}
onClick={e => {
e.preventDefault();

dispatch(_push('/data/sql'));

dispatch({
type: SET_SQL,
data: p.function_definition,
});
}}
<RawSqlButton
dataTestId={`view-function-${p.function_name}`}
customStyles={styles.display_inline}
sql={p.function_definition}
dispatch={dispatch}
>
View
</Button>
</RawSqlButton>
</div>
<div className={styles.display_inline}>{p.function_name}</div>
</div>
Expand Down
Loading