From 66479870ad2209436d5aade11af461f8935721ca Mon Sep 17 00:00:00 2001 From: Gavin Date: Sun, 12 Jul 2020 01:14:04 -0400 Subject: [PATCH 01/73] feat(console): Add "identity" frequently used column, refactor to TS --- ...or.js => FrequentlyUsedColumnSelector.tsx} | 37 +++++++- .../src/shared/utils/postgresColumnTypes.ts | 94 +++++++++++++++++++ 2 files changed, 128 insertions(+), 3 deletions(-) rename console/src/components/Services/Data/Common/Components/{FrequentlyUsedColumnSelector.js => FrequentlyUsedColumnSelector.tsx} (76%) create mode 100644 console/src/shared/utils/postgresColumnTypes.ts diff --git a/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.js b/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx similarity index 76% rename from console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.js rename to console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx index 1f28dec3992..f221b8e5bb5 100644 --- a/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.js +++ b/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx @@ -1,8 +1,26 @@ import React from 'react'; import Dropdown from '../../../../Common/Dropdown/Dropdown'; import Button from '../../../../Common/Button/Button'; +import { Dispatch } from '../../../../../types'; +import { Column } from '../../../../../shared/utils/postgresColumnTypes'; -const frequentlyUsedColumns = [ +type ColumnAction = 'add' | 'modify'; +interface FrequentlyUsedColumn { + name: string; + validFor: ColumnAction[]; + type: Column | string; + typeText: string; + primary?: boolean; + default?: string; + defaultText?: string; + dependentSQLGenerator?: ( + schemaName: string, + tableName: string, + columnName: string + ) => { upSql: string; downSql: string }; +} + +const frequentlyUsedColumns: FrequentlyUsedColumn[] = [ { name: 'id', validFor: ['add'], @@ -17,6 +35,13 @@ const frequentlyUsedColumns = [ typeText: 'bigint (auto-increment)', primary: true, }, + { + name: 'id', + validFor: ['add'], + type: 'int GENERATED BY DEFAULT AS IDENTITY', + typeText: 'identity (auto-increment, PG +10 only)', + primary: true, + }, { name: 'id', validFor: ['add'], @@ -69,7 +94,7 @@ IS 'trigger to set value of column "${columnName}" to current timestamp on row u }, ]; -const getFreqUsedColDisplayInfo = c => { +const getFreqUsedColDisplayInfo = (c: FrequentlyUsedColumn) => { const title = c.name; const typeText = c.typeText + '; '; @@ -87,11 +112,17 @@ const getFreqUsedColDisplayInfo = c => { }; }; +interface FrequentlyUsedColumnSelectorProps { + onSelect: Function; + action: ColumnAction | null; + dispatch: Dispatch | null; +} + const FrequentlyUsedColumnSelector = ({ onSelect, action = null, dispatch = null, -}) => { +}: FrequentlyUsedColumnSelectorProps) => { const frequentlyUsedColumnsOptions = () => { return frequentlyUsedColumns .filter(fuc => !action || fuc.validFor.includes(action)) diff --git a/console/src/shared/utils/postgresColumnTypes.ts b/console/src/shared/utils/postgresColumnTypes.ts new file mode 100644 index 00000000000..59e8a8c48ad --- /dev/null +++ b/console/src/shared/utils/postgresColumnTypes.ts @@ -0,0 +1,94 @@ +/** + * THIS IS A WORK IN PROGRESS + */ + +export interface IntegerColumnType { + int2: number; + int4: number; + int8: number; + smallint: number; + int: number; + bigint: number; +} + +export interface PrecisionColumnType { + real: number; + float4: number; + float: number; + float8: number; + numeric: number; + decimal: number; +} + +export interface SerialColumnType { + smallserial: number; + serial: number; + bigserial: number; +} + +export interface StringColumnType { + uuid: string; + text: string; + varchar: string; + char: string; + citext: string; +} + +export interface BooleanColumnType { + bit: boolean; + bool: boolean; + boolean: boolean; +} + +export interface DateTimeColumnType { + date: string; + timestamp: string; + timestamptz: string; + time: string; + timetz: string; + interval: string; +} + +export interface NetworkAddressColumnType { + inet: string; + cidr: string; + macaddr: string; + macaddr8: string; +} + +export interface MiscellaneousColumnType { + money: number; +} + +export interface JSONColumnType { + json: object; + jsonb: object; +} + +export type JSONColumn = keyof JSONColumnType; + +export interface ByteColumnType { + bytea: string; +} + +export type IntegerColumn = keyof IntegerColumnType; +export type PrecisionColumn = keyof PrecisionColumnType; +export type SerialColumn = keyof SerialColumnType; +export type StringColumn = keyof StringColumnType; +export type BooleanColumn = keyof BooleanColumnType; +export type DateTimeColumn = keyof DateTimeColumnType; +export type NetworkAddressColumn = keyof NetworkAddressColumnType; +export type MiscellaneousColumn = keyof MiscellaneousColumnType; +export type ByteColumn = keyof ByteColumnType; + +export type Column = + | IntegerColumn + | PrecisionColumn + | SerialColumn + | StringColumn + | BooleanColumn + | DateTimeColumn + | NetworkAddressColumn + | MiscellaneousColumn + | JSONColumn + | ByteColumn; From bb5a5bd8f9e58d1db18ab56f8f37b3fba36708b4 Mon Sep 17 00:00:00 2001 From: Aleksandra Sikora Date: Mon, 3 Aug 2020 18:29:15 +0200 Subject: [PATCH 02/73] Update FrequentlyUsedColumnSelector.tsx --- .../Data/Common/Components/FrequentlyUsedColumnSelector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx b/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx index f221b8e5bb5..95942527c49 100644 --- a/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx +++ b/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx @@ -97,7 +97,7 @@ IS 'trigger to set value of column "${columnName}" to current timestamp on row u const getFreqUsedColDisplayInfo = (c: FrequentlyUsedColumn) => { const title = c.name; - const typeText = c.typeText + '; '; + const typeText = `${c.typeText}; `; const defaultText = c.defaultText || c.default ? `default: ${c.defaultText || c.default}; ` From 6dab31d7fbd101816e38bf698479e6bf25b09965 Mon Sep 17 00:00:00 2001 From: Aleksandra Sikora Date: Mon, 3 Aug 2020 18:42:58 +0200 Subject: [PATCH 03/73] lint --- .../FrequentlyUsedColumnSelector.tsx | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx b/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx index 95942527c49..c716529a60c 100644 --- a/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx +++ b/console/src/components/Services/Data/Common/Components/FrequentlyUsedColumnSelector.tsx @@ -123,32 +123,30 @@ const FrequentlyUsedColumnSelector = ({ action = null, dispatch = null, }: FrequentlyUsedColumnSelectorProps) => { - const frequentlyUsedColumnsOptions = () => { - return frequentlyUsedColumns - .filter(fuc => !action || fuc.validFor.includes(action)) - .map(fuc => { - const { title, subTitle } = getFreqUsedColDisplayInfo(fuc); - return { - content: ( + const frequentlyUsedColumnsOptions = frequentlyUsedColumns + .filter(fuc => !action || fuc.validFor.includes(action)) + .map(fuc => { + const { title, subTitle } = getFreqUsedColDisplayInfo(fuc); + return { + content: ( +
-
- {title} -
-
{subTitle}
+ {title}
- ), - onClick: () => (dispatch ? dispatch(onSelect(fuc)) : onSelect(fuc)), - }; - }); - }; +
{subTitle}
+
+ ), + onClick: () => (dispatch ? dispatch(onSelect(fuc)) : onSelect(fuc)), + }; + }); return ( @@ -148,7 +162,8 @@ class Edit extends React.Component { e.preventDefault(); this.handleDeleteRemoteSchema(e); }} - disabled={isRequesting} + disabled={isRequesting || inconsistencyDetails} + title={inconsistencyDetails ? fixInconsistencyMsg : ''} data-test={'remote-schema-edit-delete-btn'} > {isRequesting ? 'Deleting ...' : 'Delete'} @@ -254,6 +269,7 @@ const mapStateToProps = state => { ...state.remoteSchemas.headerData, allRemoteSchemas: state.remoteSchemas.listData.remoteSchemas, dataHeaders: { ...state.tables.dataHeaders }, + inconsistentObjects: state.metadata.inconsistentObjects, }; }; diff --git a/console/src/components/Services/RemoteSchema/Edit/View.js b/console/src/components/Services/RemoteSchema/Edit/View.js index 05348e372da..9afb3036fc2 100644 --- a/console/src/components/Services/RemoteSchema/Edit/View.js +++ b/console/src/components/Services/RemoteSchema/Edit/View.js @@ -1,28 +1,56 @@ import React from 'react'; - import CommonTabLayout from '../../../Common/Layout/CommonTabLayout/CommonTabLayout'; import tabInfo from './tabInfo'; -import Tooltip from 'react-bootstrap/lib/Tooltip'; -import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger'; import { push } from 'react-router-redux'; - import { fetchRemoteSchema, RESET, getHeaderEvents, } from '../Add/addRemoteSchemaReducer'; - import { VIEW_REMOTE_SCHEMA } from '../Actions'; import ReloadRemoteSchema from '../../Settings/MetadataOptions/ReloadRemoteSchema'; - import { appPrefix } from '../constants'; - -import { NotFoundError } from '../../../Error/PageNotFound'; - import globals from '../../../../Globals'; +import styles from '../RemoteSchema.scss'; +import ToolTip from '../../../Common/Tooltip/Tooltip'; +import WarningSymbol from '../../../Common/WarningSymbol/WarningSymbol'; const prefixUrl = globals.urlPrefix + appPrefix; +const RSHeadersDisplay = ({ data }) => + data.length > 0 ? ( + + Headers + + {data && + data + .filter(header => !!header.name) + .map((header, index) => [ + + + {`${header.name}: `} + {header.type === 'static' + ? header.value + : '<' + header.value + '>'} + + , + index !== data.length - 1 ?
: null, + ])} + + + ) : null; + +const RSReloadSchema = ({ readOnlyMode, remoteSchemaName, ...props }) => + !readOnlyMode && remoteSchemaName && remoteSchemaName.length > 0 ? ( +
+ + +
+ ) : null; + class ViewStitchedSchema extends React.Component { componentDidMount() { const { remoteSchemaName } = this.props.params; @@ -35,17 +63,17 @@ class ViewStitchedSchema extends React.Component { ]); } - UNSAFE_componentWillReceiveProps(nextProps) { + componentDidUpdate(prevProps) { if ( - nextProps.params.remoteSchemaName !== this.props.params.remoteSchemaName + prevProps.params.remoteSchemaName !== this.props.params.remoteSchemaName ) { Promise.all([ this.props.dispatch( - fetchRemoteSchema(nextProps.params.remoteSchemaName) + fetchRemoteSchema(this.props.params.remoteSchemaName) ), this.props.dispatch({ type: VIEW_REMOTE_SCHEMA, - data: nextProps.params.remoteSchemaName, + data: this.props.params.remoteSchemaName, }), ]); } @@ -69,19 +97,14 @@ class ViewStitchedSchema extends React.Component { } render() { - const currentRemoteSchema = this.props.allRemoteSchemas.find( - r => r.name === this.props.params.remoteSchemaName - ); - - if (!currentRemoteSchema) { - // throw a 404 exception - throw new NotFoundError(); - } - - const styles = require('../RemoteSchema.scss'); - const { remoteSchemaName } = this.props.params; - const { manualUrl, envName, headers, readOnlyMode } = this.props; + const { + manualUrl, + envName, + headers, + readOnlyMode, + inconsistentObjects, + } = this.props; const filterHeaders = headers.filter(h => !!h.name); @@ -92,21 +115,14 @@ class ViewStitchedSchema extends React.Component { }, { title: 'Manage', - url: appPrefix + '/' + 'manage', + url: `${appPrefix}/manage`, }, ]; if (remoteSchemaName) { breadCrumbs.push({ title: remoteSchemaName.trim(), - url: - appPrefix + - '/' + - 'manage' + - '/' + - remoteSchemaName.trim() + - '/' + - 'details', + url: `${appPrefix}/manage/${remoteSchemaName.trim()}/details`, }); breadCrumbs.push({ title: 'details', @@ -114,33 +130,18 @@ class ViewStitchedSchema extends React.Component { }); } - const refresh = ( - - If your remote schema has changed, you need to refresh the GraphQL - Engine metadata to query the modified schema - - ); + let tabInfoCopy = tabInfo; if (readOnlyMode) { - delete tabInfo.modify; + const { modify, ...rest } = tabInfoCopy; + tabInfoCopy = rest; } - const showReloadRemoteSchema = - !readOnlyMode && remoteSchemaName && remoteSchemaName.length > 0 ? ( -
- - - - - -