From dc4713b9d3d66b5084bc64c0f5278e03ea8fd5a0 Mon Sep 17 00:00:00 2001 From: Ikechukwu Eze Date: Wed, 8 Sep 2021 15:10:54 +0100 Subject: [PATCH] console: refactor PermissionBuilder.js to typescript ### Changelog no changelog required ### Affected components - [ ] Server - [x] Console - [ ] CLI - [ ] Docs - [ ] Community Content - [ ] Build System - [ ] Tests - [ ] Other (list it) https://github.com/hasura/graphql-engine-mono/pull/2122 GitOrigin-RevId: d12d225454659621198286c15965345c7a8a8e01 --- .../src/components/Common/utils/jsUtils.tsx | 8 +- ...issionBuilder.js => PermissionBuilder.tsx} | 610 ++++++++++-------- .../PermissionBuilder/SelectGroup.tsx | 2 +- console/src/dataSources/types.ts | 1 + 4 files changed, 334 insertions(+), 287 deletions(-) rename console/src/components/Services/Data/TablePermissions/PermissionBuilder/{PermissionBuilder.js => PermissionBuilder.tsx} (64%) diff --git a/console/src/components/Common/utils/jsUtils.tsx b/console/src/components/Common/utils/jsUtils.tsx index c27a82ca05b..8311f500c06 100644 --- a/console/src/components/Common/utils/jsUtils.tsx +++ b/console/src/components/Common/utils/jsUtils.tsx @@ -165,7 +165,11 @@ export const isStringArray = (str: string): boolean => { /* JSON utils */ -export function getAllJsonPaths(json: any, leafKeys: any[], prefix = '') { +export function getAllJsonPaths( + json: any, + leafKeys: any[], + prefix = '' +): Record[] | string[] { const paths = []; const addPrefix = (subPath: string) => { @@ -175,7 +179,7 @@ export function getAllJsonPaths(json: any, leafKeys: any[], prefix = '') { const handleSubJson = (subJson: any, newPrefix: string) => { const subPaths = getAllJsonPaths(subJson, leafKeys, newPrefix); - subPaths.forEach(subPath => { + subPaths.forEach((subPath: typeof subPaths[0]) => { paths.push(subPath); }); diff --git a/console/src/components/Services/Data/TablePermissions/PermissionBuilder/PermissionBuilder.js b/console/src/components/Services/Data/TablePermissions/PermissionBuilder/PermissionBuilder.tsx similarity index 64% rename from console/src/components/Services/Data/TablePermissions/PermissionBuilder/PermissionBuilder.js rename to console/src/components/Services/Data/TablePermissions/PermissionBuilder/PermissionBuilder.tsx index b451e56f9ea..ddb537837ea 100644 --- a/console/src/components/Services/Data/TablePermissions/PermissionBuilder/PermissionBuilder.js +++ b/console/src/components/Services/Data/TablePermissions/PermissionBuilder/PermissionBuilder.tsx @@ -1,9 +1,6 @@ -/* eslint-disable no-use-before-define*/ - +/* eslint-disable @typescript-eslint/no-use-before-define */ import React from 'react'; -import PropTypes from 'prop-types'; - import { currentDriver, dataSource, @@ -41,29 +38,34 @@ import { TABLE_KEY, WHERE_KEY, } from './utils'; -import SelectGroup, { QuotedSelectGroup } from './SelectGroup'; +import SelectGroup, { OptGroup, QuotedSelectGroup } from './SelectGroup'; import { getComputedFieldFunction, getGroupedTableComputedFields, } from '../../../../../dataSources/services/postgresql'; +import { QualifiedTable } from '../../../../../metadata/types'; +import styles from './PermissionBuilder.scss'; +import { ComputedField, Table } from '../../../../../dataSources/types'; +import { Nullable } from '../../../../Common/utils/tsUtils'; +import { PGFunction } from '../../../../../dataSources/services/postgresql/types'; -class PermissionBuilder extends React.Component { - static propTypes = { - allTableSchemas: PropTypes.array.isRequired, - allFunctions: PropTypes.array.isRequired, - schemaList: PropTypes.array.isRequired, - dispatch: PropTypes.func.isRequired, - dispatchFuncSetFilter: PropTypes.func.isRequired, - loadSchemasFunc: PropTypes.func.isRequired, - filter: PropTypes.string, - tableDef: PropTypes.object.isRequired, - }; +interface PermissionBuilderProps { + allTableSchemas: Table[]; + allFunctions: PGFunction[]; + schemaList: string[]; + dispatch: () => void; + dispatchFuncSetFilter: (filter: string) => void; + loadSchemasFunc: (schemaNames: string[]) => void; + filter: string; + tableDef: QualifiedTable; +} +class PermissionBuilder extends React.Component { componentDidMount() { this.loadMissingSchemas(); } - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps: PermissionBuilderProps) { // check for and fetch any missing schemas if // either permission filter or available table schemas have changed if ( @@ -80,35 +82,38 @@ class PermissionBuilder extends React.Component { ) { const { loadSchemasFunc } = this.props; - const findMissingSchemas = (path, currTable) => { - let _missingSchemas = []; + const findMissingSchemas = ( + path: Record | string[] | string, + currTable: QualifiedTable + ): string[] => { + let missingSchemas = []; - let value; + let value: any; if (isObject(path)) { value = Object.values(path)[0]; path = Object.keys(path)[0]; } - const getNewPath = newPath => { + const getNewPath = (newPath: string) => { return value ? { [newPath]: value } : newPath; }; - const pathSplit = path.split('.'); + const pathSplit = (path as string).split('.'); const operator = pathSplit[0]; if (isArrayBoolOperator(operator)) { const newPath = getNewPath(pathSplit.slice(2).join('.')); - _missingSchemas = findMissingSchemas(newPath, currTable); + missingSchemas = findMissingSchemas(newPath, currTable); } else if (isBoolOperator(operator)) { const newPath = getNewPath(pathSplit.slice(1).join('.')); - _missingSchemas = findMissingSchemas(newPath, currTable); + missingSchemas = findMissingSchemas(newPath, currTable); } else if (isExistOperator(operator)) { const existTableDef = getQualifiedTableDef(value[TABLE_KEY]); let existTableSchema; if (existTableDef) { - existTableSchema = existTableDef.schema; + existTableSchema = (existTableDef as QualifiedTable).schema; } const existWhere = value[WHERE_KEY] || ''; @@ -119,17 +124,20 @@ class PermissionBuilder extends React.Component { const allSchemaNames = allTableSchemas.map(t => t.table_schema); if (!allSchemaNames.includes(existTableSchema)) { - _missingSchemas.push(existTableSchema); + missingSchemas.push(existTableSchema); } } - this.loadMissingSchemas(existTableDef, JSON.stringify(existWhere)); + this.loadMissingSchemas( + existTableDef as QualifiedTable, + JSON.stringify(existWhere) + ); } else if (isColumnOperator(operator)) { // no missing schemas } else { const { allTableSchemas } = this.props; - let tableRelationshipNames = []; + let tableRelationshipNames: string[] = []; const tableSchema = findTable(allTableSchemas, currTable); @@ -138,30 +146,29 @@ class PermissionBuilder extends React.Component { } if (tableRelationshipNames.includes(operator)) { - const relationship = getTableRelationship(tableSchema, operator); - const refTable = getRelationshipRefTable(tableSchema, relationship); + const relationship = getTableRelationship(tableSchema!, operator); + const refTable = getRelationshipRefTable(tableSchema!, relationship!); - const refTableSchema = findTable(allTableSchemas, refTable); + const refTableSchema = findTable(allTableSchemas, refTable!); if (!refTableSchema) { - _missingSchemas.push(refTable.schema); + missingSchemas.push(refTable!.schema); } const newPath = getNewPath(pathSplit.slice(1).join('.')); - _missingSchemas.push(...findMissingSchemas(newPath, refTable)); + missingSchemas.push(...findMissingSchemas(newPath, refTable!)); } else { // no missing schemas } } - return _missingSchemas; + return missingSchemas; }; - const missingSchemas = []; + const missingSchemas: string[] = []; const paths = getAllJsonPaths(JSON.parse(filter || '{}'), existOperators); - paths.forEach(path => { + paths.forEach((path: Record | string) => { const subMissingSchemas = findMissingSchemas(path, tableDef); - missingSchemas.push(...subMissingSchemas); }); @@ -171,68 +178,71 @@ class PermissionBuilder extends React.Component { } render() { - const styles = require('./PermissionBuilder.scss'); - - const wrapDoubleQuotes = value => { + const wrapDoubleQuotes = (value: JSX.Element) => { return ( - "  + "  {value} -  " +  " ); }; - /********************************/ + /* ****************************** */ - const getFilter = (defaultSchema, conditions, prefix, value = '') => { - let _boolExp = {}; + const getFilter = ( + defaultSchema: string, + conditions: Record, + prefix: string, + value = '' + ) => { + let boolExp = {}; const getArrayBoolOperatorFilter = ( - operator, - opValue, - opConditions, - opPrefix, - isLast + operator: string, + opValue: string, + opConditions: Record[], + opPrefix: string, + isLast: boolean ) => { - const _filter = {}; + const filter: Record> = {}; if (isLast) { - _filter[operator] = []; + filter[operator] = []; } else { const opPrefixSplit = opPrefix.split('.'); const position = parseInt(opPrefixSplit[0], 10); const newPrefix = opPrefixSplit.slice(1).join('.'); - _filter[operator] = opConditions; - _filter[operator][position] = getFilter( + filter[operator] = opConditions; + filter[operator][position] = getFilter( defaultSchema, opConditions[position], newPrefix, opValue ); - if (Object.keys(_filter[operator][position]).length === 0) { - _filter[operator].splice(position, 1); + if (Object.keys(filter[operator][position]).length === 0) { + filter[operator].splice(position, 1); } } - return _filter; + return filter; }; const getBoolOperatorFilter = ( - operator, - opValue, - opConditions, - opPrefix, - isLast + operator: string, + opValue: string, + opConditions: Record[], + opPrefix: string, + isLast: boolean ) => { - const _filter = {}; + const filter: Record> = {}; if (isLast) { - _filter[operator] = {}; + filter[operator] = {}; } else { - _filter[operator] = getFilter( + filter[operator] = getFilter( defaultSchema, opConditions, opPrefix, @@ -240,66 +250,65 @@ class PermissionBuilder extends React.Component { ); } - return _filter; + return filter; }; const getArrayColumnOperatorFilter = ( - operator, - opValue, - opConditions, - opPrefix, - isLast + operator: string, + opValue: string, + opConditions: string[], + opPrefix: string, + isLast: boolean ) => { - const _filter = {}; + const filter: Record = {}; if (isLast) { - _filter[operator] = opValue || []; + filter[operator] = opValue || []; } else { const opPrefixSplit = opPrefix.split('.'); const position = parseInt(opPrefixSplit[0], 10); - _filter[operator] = opConditions || []; + filter[operator] = opConditions || []; if (opValue !== '') { - _filter[operator][position] = opValue; + filter[operator][position] = opValue; } else { - _filter[operator].splice(position, 1); + filter[operator].splice(position, 1); } } - return _filter; + return filter; }; - const getColumnOperatorFilter = (operator, opValue) => { - const _filter = {}; - - _filter[operator] = opValue; - - return _filter; + const getColumnOperatorFilter = (operator: string, opValue: string) => { + const filter: Record = {}; + filter[operator] = opValue; + return filter; }; const getExistsOperatorFilter = ( - operator, - opValue, - opConditions, - opPrefix, - isLast + operator: string, + // HACK: justifitied any + opValue: any, + opConditions: Record>, + opPrefix: string, + isLast: boolean ) => { - const _filter = { + const filter = { [operator]: opConditions, }; if (isLast) { - _filter[operator] = { + filter[operator] = { [TABLE_KEY]: generateTableDef('', defaultSchema), [WHERE_KEY]: {}, }; } else if (opPrefix === TABLE_KEY) { - _filter[operator] = { + filter[operator] = { [TABLE_KEY]: opValue, [WHERE_KEY]: {}, }; } else if (opPrefix === WHERE_KEY) { - _filter[operator][WHERE_KEY] = getFilter( + filter[operator][WHERE_KEY] = getFilter( defaultSchema, opConditions[opPrefix], opValue.prefix, @@ -307,22 +316,22 @@ class PermissionBuilder extends React.Component { ); } - return _filter; + return filter; }; const getColumnFilter = ( - operator, - opValue, - opConditions, - opPrefix, - isLast + operator: string, + opValue: string, + opConditions: Record, + opPrefix: string, + isLast: boolean ) => { - const _filter = {}; + const filter: Record> = {}; if (isLast) { - _filter[operator] = {}; + filter[operator] = {}; } else { - _filter[operator] = getFilter( + filter[operator] = getFilter( defaultSchema, opConditions, opPrefix, @@ -330,7 +339,7 @@ class PermissionBuilder extends React.Component { ); } - return _filter; + return filter; }; const prefixSplit = prefix.split('.'); @@ -345,7 +354,7 @@ class PermissionBuilder extends React.Component { if (operator === '') { // blank bool exp } else if (isArrayBoolOperator(operator)) { - _boolExp = getArrayBoolOperatorFilter( + boolExp = getArrayBoolOperatorFilter( operator, value, opConditions, @@ -353,7 +362,7 @@ class PermissionBuilder extends React.Component { isLast ); } else if (isBoolOperator(operator)) { - _boolExp = getBoolOperatorFilter( + boolExp = getBoolOperatorFilter( operator, value, opConditions, @@ -361,7 +370,7 @@ class PermissionBuilder extends React.Component { isLast ); } else if (isArrayColumnOperator(operator)) { - _boolExp = getArrayColumnOperatorFilter( + boolExp = getArrayColumnOperatorFilter( operator, value, opConditions, @@ -369,9 +378,9 @@ class PermissionBuilder extends React.Component { isLast ); } else if (isColumnOperator(operator)) { - _boolExp = getColumnOperatorFilter(operator, value); + boolExp = getColumnOperatorFilter(operator, value); } else if (isExistOperator(operator)) { - _boolExp = getExistsOperatorFilter( + boolExp = getExistsOperatorFilter( operator, value, opConditions, @@ -379,7 +388,7 @@ class PermissionBuilder extends React.Component { isLast ); } else { - _boolExp = getColumnFilter( + boolExp = getColumnFilter( operator, value, opConditions, @@ -388,52 +397,31 @@ class PermissionBuilder extends React.Component { ); } - return _boolExp; + return boolExp; }; - const _dispatchFunc = data => { + // eslint-disable-next-line no-underscore-dangle + const _dispatchFunc = (data: { prefix: string; value?: string }) => { const { filter, dispatchFuncSetFilter, tableDef } = this.props; - const newFilter = getFilter( tableDef.schema, JSON.parse(filter || '{}'), data.prefix, data.value ); - - // dispatchFuncSetFilter(JSON.stringify(newFilter, null, 4)); dispatchFuncSetFilter(JSON.stringify(newFilter)); }; - /********************************/ - - const renderBoolSelect = ( - selectDispatchFunc, - value, - prefix = '', - disabledValues = [] - ) => { - const _value = typeof value === 'boolean' ? value.toString() : ''; - - const values = ['true', 'false']; - - return renderSelect( - selectDispatchFunc, - _value, - values, - prefix, - disabledValues - ); - }; + /* ****************************** */ const renderSelect = ( - selectDispatchFunc, - value, - values, + selectDispatchFunc: (val: string) => void, + value: string, + values: string[] | OptGroup[], prefix = '', - disabledValues = [] + disabledValues: string[] = [] ) => { - const dispatchSelect = e => { + const dispatchSelect = (e: React.ChangeEvent) => { selectDispatchFunc(e.target.value); }; @@ -442,17 +430,17 @@ class PermissionBuilder extends React.Component { ); } - const _selectOptions = []; - [''].concat(values).forEach((val, i) => { + const selectOptions: JSX.Element[] = []; + [''].concat(values as string[]).forEach((val, i) => { const optionVal = addToPrefix(prefix, val); - _selectOptions.push( + selectOptions.push(