mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 17:31:56 +03:00
This commit is contained in:
parent
de09c29003
commit
0b3defd314
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Select, { components } from 'react-select';
|
import Select, { components, createFilter } from 'react-select';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -16,6 +16,14 @@ const CustomOption = props => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getPrefixFilter = () => {
|
||||||
|
const prefixFilterOptions = {
|
||||||
|
matchFrom: 'start',
|
||||||
|
};
|
||||||
|
|
||||||
|
return createFilter(prefixFilterOptions);
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Searchable select box component
|
* Searchable select box component
|
||||||
* 1) options: Accepts options
|
* 1) options: Accepts options
|
||||||
@ -30,6 +38,7 @@ const SearchableSelectBox = ({
|
|||||||
value,
|
value,
|
||||||
bsClass,
|
bsClass,
|
||||||
styleOverrides,
|
styleOverrides,
|
||||||
|
filterOption,
|
||||||
}) => {
|
}) => {
|
||||||
/* Select element style customization */
|
/* Select element style customization */
|
||||||
|
|
||||||
@ -45,6 +54,15 @@ const SearchableSelectBox = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let customFilter;
|
||||||
|
switch (filterOption) {
|
||||||
|
case 'prefix':
|
||||||
|
customFilter = getPrefixFilter();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
customFilter = {};
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
isSearchable
|
isSearchable
|
||||||
@ -55,6 +73,7 @@ const SearchableSelectBox = ({
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
value={value}
|
value={value}
|
||||||
styles={customStyles}
|
styles={customStyles}
|
||||||
|
filterOption={customFilter}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -65,6 +84,7 @@ SearchableSelectBox.propTypes = {
|
|||||||
options: PropTypes.array.isRequired,
|
options: PropTypes.array.isRequired,
|
||||||
bsClass: PropTypes.string,
|
bsClass: PropTypes.string,
|
||||||
customStyle: PropTypes.object,
|
customStyle: PropTypes.object,
|
||||||
|
filterOption: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SearchableSelectBox;
|
export default SearchableSelectBox;
|
||||||
|
@ -91,6 +91,7 @@ const TableColumn = props => {
|
|||||||
value={column.type && columnTypeValueMap[column.type]}
|
value={column.type && columnTypeValueMap[column.type]}
|
||||||
bsClass={`col-type-${i} add_table_column_selector`}
|
bsClass={`col-type-${i} add_table_column_selector`}
|
||||||
styleOverrides={customSelectBoxStyles}
|
styleOverrides={customSelectBoxStyles}
|
||||||
|
filterOption={'prefix'}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
|
@ -34,23 +34,27 @@ const getAllDataTypeMap = allDataTypes => {
|
|||||||
return dTIndex;
|
return dTIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDataTypeInfo = (row, categoryInfo, colId) => {
|
const getDataTypeInfo = (row, categoryInfo, colId, cached = {}) => {
|
||||||
const columnTypeValueMap = {};
|
const columnTypeValueMap = {};
|
||||||
|
|
||||||
const { typInfo, typDisplayName, typDescription } = splitDbRow(row);
|
const { typInfo, typDisplayName, typDescription } = splitDbRow(row);
|
||||||
|
|
||||||
// Create option object for every valid type
|
// Create option object for every valid type
|
||||||
const currTypeObj = typInfo.map((t, i) => {
|
const currTypeObj = [];
|
||||||
const optObj = {
|
typInfo.forEach((t, i) => {
|
||||||
value: t,
|
/* Don't add types which are part of frequently used types */
|
||||||
label: typDisplayName[i],
|
if (!(t in cached)) {
|
||||||
key: `${categoryInfo}_${i}`,
|
const optObj = {
|
||||||
colIdentifier: colId,
|
value: t,
|
||||||
description: typDescription[i],
|
label: typDisplayName[i],
|
||||||
};
|
key: `${categoryInfo}_${i}`,
|
||||||
// Memoizing option for later use
|
colIdentifier: colId,
|
||||||
columnTypeValueMap[t] = optObj;
|
description: typDescription[i],
|
||||||
return optObj;
|
};
|
||||||
|
// Memoizing option for later use
|
||||||
|
columnTypeValueMap[t] = optObj;
|
||||||
|
currTypeObj.push(optObj);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return { typInfo: currTypeObj, typValueMap: columnTypeValueMap };
|
return { typInfo: currTypeObj, typValueMap: columnTypeValueMap };
|
||||||
};
|
};
|
||||||
@ -99,7 +103,8 @@ const getDataOptions = (commonDataTypes, restTypes, identifier) => {
|
|||||||
const { typInfo, typValueMap } = getDataTypeInfo(
|
const { typInfo, typValueMap } = getDataTypeInfo(
|
||||||
categoryRow[0],
|
categoryRow[0],
|
||||||
pgCategoryCode[category],
|
pgCategoryCode[category],
|
||||||
identifier
|
identifier,
|
||||||
|
columnTypeValueMap
|
||||||
);
|
);
|
||||||
columnTypeValueMap = { ...columnTypeValueMap, ...typValueMap };
|
columnTypeValueMap = { ...columnTypeValueMap, ...typValueMap };
|
||||||
columnDataTypes.push({
|
columnDataTypes.push({
|
||||||
|
@ -697,7 +697,7 @@ const dataReducer = (state = defaultState, action) => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
columnDataTypes: action.data,
|
columnDataTypes: action.data,
|
||||||
columnDataTypeFetchErr: 'Error fetching data',
|
columnDataTypeFetchErr: defaultState.columnDataTypeFetchErr,
|
||||||
};
|
};
|
||||||
|
|
||||||
case FETCH_COLUMN_TYPE_LIST_FAIL:
|
case FETCH_COLUMN_TYPE_LIST_FAIL:
|
||||||
@ -710,7 +710,7 @@ const dataReducer = (state = defaultState, action) => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
columnDataTypes: [...defaultState.columnDataTypes],
|
columnDataTypes: [...defaultState.columnDataTypes],
|
||||||
columnDataTypeFetchErr: defaultState.columnDataTypes,
|
columnDataTypeFetchErr: defaultState.columnDataTypeFetchErr,
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
@ -152,6 +152,7 @@ const ColumnCreator = ({ dispatch, tableName, dataTypes: restTypes = [] }) => {
|
|||||||
value={colType.value && columnTypeValueMap[colType.value]}
|
value={colType.value && columnTypeValueMap[colType.value]}
|
||||||
bsClass={`col-type-${0} modify_select`}
|
bsClass={`col-type-${0} modify_select`}
|
||||||
styleOverrides={customSelectBoxStyles}
|
styleOverrides={customSelectBoxStyles}
|
||||||
|
filterOption={'prefix'}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
|
@ -2,20 +2,6 @@ import React, { useEffect } from 'react';
|
|||||||
|
|
||||||
import SearchableSelectBox from '../../../Common/SearchableSelect/SearchableSelect';
|
import SearchableSelectBox from '../../../Common/SearchableSelect/SearchableSelect';
|
||||||
|
|
||||||
/*
|
|
||||||
import {
|
|
||||||
INTEGER,
|
|
||||||
SERIAL,
|
|
||||||
BIGINT,
|
|
||||||
BIGSERIAL,
|
|
||||||
UUID,
|
|
||||||
JSONDTYPE,
|
|
||||||
JSONB,
|
|
||||||
TIMESTAMP,
|
|
||||||
TIME,
|
|
||||||
} from '../../../../constants';
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { getValidAlterOptions } from './utils';
|
import { getValidAlterOptions } from './utils';
|
||||||
|
|
||||||
const ColumnEditor = ({
|
const ColumnEditor = ({
|
||||||
@ -113,6 +99,7 @@ const ColumnEditor = ({
|
|||||||
value={columnTypePG && alterOptionsValueMap[columnTypePG]}
|
value={columnTypePG && alterOptionsValueMap[columnTypePG]}
|
||||||
bsClass={`col-type-${0} modify_select`}
|
bsClass={`col-type-${0} modify_select`}
|
||||||
styleOverrides={customSelectBoxStyles}
|
styleOverrides={customSelectBoxStyles}
|
||||||
|
filterOption={'prefix'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,10 +34,10 @@ const getValidAlterOptions = (alterTypeOptions, colName) => {
|
|||||||
const fetchColumnCastsQuery = `
|
const fetchColumnCastsQuery = `
|
||||||
SELECT ts.typname AS "Source Type",
|
SELECT ts.typname AS "Source Type",
|
||||||
pg_catalog.format_type(castsource, NULL) AS "Source Info",
|
pg_catalog.format_type(castsource, NULL) AS "Source Info",
|
||||||
pg_catalog.obj_description(castsource, 'pg_type') as "Source Descriptions",
|
coalesce(pg_catalog.obj_description(castsource, 'pg_type'), '') as "Source Descriptions",
|
||||||
string_agg(tt.typname, ',') AS "Target Type",
|
string_agg(tt.typname, ',') AS "Target Type",
|
||||||
string_agg(pg_catalog.format_type(casttarget, NULL), ',') AS "Target Info",
|
string_agg(pg_catalog.format_type(casttarget, NULL), ',') AS "Target Info",
|
||||||
string_agg(pg_catalog.obj_description(casttarget, 'pg_type'), ':') as "Target Descriptions",
|
string_agg(coalesce(pg_catalog.obj_description(casttarget, 'pg_type'), ''), ':') as "Target Descriptions",
|
||||||
string_agg(CASE WHEN castfunc = 0 THEN '(binary coercible)'
|
string_agg(CASE WHEN castfunc = 0 THEN '(binary coercible)'
|
||||||
ELSE p.proname
|
ELSE p.proname
|
||||||
END, ',') as "Function"
|
END, ',') as "Function"
|
||||||
@ -59,15 +59,26 @@ ORDER BY 1, 2;
|
|||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const getCreatePkSql = ({ schemaName, tableName, selectedPkColumns, constraintName }) => {
|
const getCreatePkSql = ({
|
||||||
|
schemaName,
|
||||||
|
tableName,
|
||||||
|
selectedPkColumns,
|
||||||
|
constraintName,
|
||||||
|
}) => {
|
||||||
return `alter table "${schemaName}"."${tableName}"
|
return `alter table "${schemaName}"."${tableName}"
|
||||||
add constraint "${constraintName}" primary key ( ${selectedPkColumns
|
add constraint "${constraintName}" primary key ( ${selectedPkColumns
|
||||||
.map(pkc => `"${pkc}"`)
|
.map(pkc => `"${pkc}"`)
|
||||||
.join(', ')} );`;
|
.join(', ')} );`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDropPkSql = ({ schemaName, tableName, constraintName }) => {
|
const getDropPkSql = ({ schemaName, tableName, constraintName }) => {
|
||||||
return `alter table "${schemaName}"."${tableName}" drop constraint "${constraintName}";`;
|
return `alter table "${schemaName}"."${tableName}" drop constraint "${constraintName}";`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { convertArrayToJson, getValidAlterOptions, fetchColumnCastsQuery, getCreatePkSql, getDropPkSql };
|
export {
|
||||||
|
convertArrayToJson,
|
||||||
|
getValidAlterOptions,
|
||||||
|
fetchColumnCastsQuery,
|
||||||
|
getCreatePkSql,
|
||||||
|
getDropPkSql,
|
||||||
|
};
|
||||||
|
@ -569,11 +569,15 @@ export const commonDataTypes = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetch non-composite types, primitive types like text, varchar etc,
|
||||||
|
* Filter types whose typename is unknown and type category is not 'Pseudo' and it is valid and available to be used
|
||||||
|
* */
|
||||||
export const fetchColumnTypesQuery = `
|
export const fetchColumnTypesQuery = `
|
||||||
SELECT
|
SELECT
|
||||||
string_agg(t.typname, ',') as "Type Name",
|
string_agg(t.typname, ',') as "Type Name",
|
||||||
string_agg(pg_catalog.format_type(t.oid, NULL), ',') as "Display Name",
|
string_agg(pg_catalog.format_type(t.oid, NULL), ',') as "Display Name",
|
||||||
string_agg(pg_catalog.obj_description(t.oid, 'pg_type'), ':') as "Descriptions",
|
string_agg(coalesce(pg_catalog.obj_description(t.oid, 'pg_type'), ''), ':') as "Descriptions",
|
||||||
t.typcategory
|
t.typcategory
|
||||||
FROM pg_catalog.pg_type t
|
FROM pg_catalog.pg_type t
|
||||||
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
||||||
|
@ -225,7 +225,7 @@ const ViewRows = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const successIcon = (
|
const successIcon = (
|
||||||
<i className={styles.invocationSuccess + 'fa fa-check'} />
|
<i className={styles.invocationSuccess + ' fa fa-check'} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const failureIcon = (
|
const failureIcon = (
|
||||||
@ -437,26 +437,26 @@ const ViewRows = ({
|
|||||||
>
|
>
|
||||||
{finalResponse.status_code
|
{finalResponse.status_code
|
||||||
? [
|
? [
|
||||||
'Status Code: ',
|
'Status Code: ',
|
||||||
verifySuccessStatus(
|
verifySuccessStatus(
|
||||||
finalResponse.status_code
|
finalResponse.status_code
|
||||||
)
|
)
|
||||||
? successIcon
|
? successIcon
|
||||||
: failureIcon,
|
: failureIcon,
|
||||||
finalResponse.status_code,
|
finalResponse.status_code,
|
||||||
' ',
|
' ',
|
||||||
<OverlayTrigger
|
<OverlayTrigger
|
||||||
placement="top"
|
placement="top"
|
||||||
overlay={
|
overlay={
|
||||||
tooltip.statusCodeDescription
|
tooltip.statusCodeDescription
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
className="fa fa-question-circle"
|
className="fa fa-question-circle"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
</OverlayTrigger>,
|
</OverlayTrigger>,
|
||||||
]
|
]
|
||||||
: null}
|
: null}
|
||||||
</div>
|
</div>
|
||||||
<AceEditor
|
<AceEditor
|
||||||
|
Loading…
Reference in New Issue
Block a user