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

feat: indicate schema description loading #1672

Merged
merged 6 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 7 additions & 35 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ jobs:
rm -rf gh-pages/$REPORT_DIR
mkdir -p gh-pages/$REPORT_DIR
cp -r playwright-artifacts/playwright-report/* gh-pages/$REPORT_DIR/
# Also copy test-results.json if it exists
if [ -f "playwright-artifacts/test-results.json" ]; then
cp playwright-artifacts/test-results.json gh-pages/$REPORT_DIR/
fi

- name: Deploy report to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
Expand Down Expand Up @@ -217,34 +221,6 @@ jobs:
name: playwright-artifacts
path: playwright-artifacts

- name: Count new tests
id: count_tests
run: |
git fetch origin main:main
new_tests=0

# Get list of changed test files
for file in $(git diff --name-only main...HEAD | grep -E '^tests/suites/.*\.(spec|test)\.(ts|tsx|js|jsx)$'); do
# Count tests in current version
if git show HEAD:"$file" > /dev/null 2>&1; then
current_tests=$(git show HEAD:"$file" | grep -E "test\([\'\"]" | wc -l)
else
current_tests=0
fi

# Count tests in main version
if git show main:"$file" > /dev/null 2>&1; then
base_tests=$(git show main:"$file" | grep -E "test\([\'\"]" | wc -l)
else
base_tests=0
fi

# Add difference to total
((new_tests += current_tests - base_tests))
done

echo "new_tests=$new_tests" >> $GITHUB_OUTPUT

- name: Update PR description
uses: actions/github-script@v6
with:
Expand Down Expand Up @@ -289,17 +265,14 @@ jobs:
parseFloat(percent) > 0 ? 'πŸ”Ί' :
parseFloat(percent) < 0 ? 'πŸ”½' : 'βœ…';

const newTests = parseInt('${{ steps.count_tests.outputs.new_tests }}');
const testsStatus = newTests > 0 ? '✨' : 'βž–';

const ciSection = `## CI Results

### Test Status: <span style="color: ${statusColor};">${status}</span>
πŸ“Š [Full Report](${reportUrl})

| Total | Passed | Failed | Flaky | Skipped | New Tests |
|:-----:|:------:|:------:|:-----:|:-------:|:---------:|
| ${testResults.total} | ${testResults.passed} | ${testResults.failed} | ${testResults.flaky} | ${testResults.skipped} | ${testsStatus} ${newTests} |
| Total | Passed | Failed | Flaky | Skipped |
|:-----:|:------:|:------:|:-----:|:-------:|
| ${testResults.total} | ${testResults.passed} | ${testResults.failed} | ${testResults.flaky} | ${testResults.skipped} |

### Bundle Size: ${bundleStatus}
Current: ${formatSize(currentSize)} | Main: ${formatSize(mainSize)}
Expand All @@ -318,7 +291,6 @@ jobs:
- Bundle size is measured for the entire 'dist' directory.
- πŸ“Š indicates links to detailed reports.
- πŸ”Ί indicates increase, πŸ”½ decrease, and βœ… no change in bundle size.
- ${testsStatus} indicates ${newTests} new test cases added in this PR.
</details>`;

const { data: pullRequest } = await github.rest.pulls.get({
Expand Down
9 changes: 5 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
},
"dependencies": {
"@bem-react/classname": "^1.6.0",
"@ebay/nice-modal-react": "^1.2.13",
"@gravity-ui/axios-wrapper": "^1.4.1",
"@gravity-ui/chartkit": "^5.9.0",
"@gravity-ui/components": "^3.7.0",
Expand All @@ -27,7 +28,6 @@
"@hookform/resolvers": "^3.9.0",
"@reduxjs/toolkit": "^2.2.3",
"@tanstack/react-table": "^8.19.3",
"@ebay/nice-modal-react": "^1.2.13",
"axios": "^1.7.3",
"axios-retry": "^4.4.2",
"colord": "^2.9.3",
Expand All @@ -53,7 +53,7 @@
"use-query-params": "^2.2.1",
"uuid": "^10.0.0",
"web-vitals": "^1.1.2",
"ydb-ui-components": "^4.2.0",
"ydb-ui-components": "^4.3.2",
"zod": "^3.23.8"
},
"scripts": {
Expand Down
84 changes: 48 additions & 36 deletions src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@ import {useCreateDirectoryFeatureAvailable} from '../../../../store/reducers/cap
import {selectUserInput} from '../../../../store/reducers/query/query';
import {schemaApi} from '../../../../store/reducers/schema/schema';
import {tableSchemaDataApi} from '../../../../store/reducers/tableSchemaData';
import type {GetTableSchemaDataParams} from '../../../../store/reducers/tableSchemaData';
import type {EPathType, TEvDescribeSchemeResult} from '../../../../types/api/schema';
import {wait} from '../../../../utils';
import {SECOND_IN_MS} from '../../../../utils/constants';
import {
useQueryExecutionSettings,
useTypedDispatch,
useTypedSelector,
} from '../../../../utils/hooks';
import {getConfirmation} from '../../../../utils/hooks/withConfirmation/useChangeInputWithConfirmation';
import {getSchemaControls} from '../../utils/controls';
import {isChildlessPathType, mapPathTypeToNavigationTreeType} from '../../utils/schema';
import {
isChildlessPathType,
mapPathTypeToNavigationTreeType,
nodeTableTypeToPathType,
} from '../../utils/schema';
import {getActions} from '../../utils/schemaActions';
import {CreateDirectoryDialog} from '../CreateDirectoryDialog/CreateDirectoryDialog';
import {useDispatchTreeKey, useTreeKey} from '../UpdateTreeContext';
Expand All @@ -33,29 +34,15 @@ interface SchemaTreeProps {
onActivePathUpdate: (path: string) => void;
}

const TABLE_SCHEMA_TIMEOUT = SECOND_IN_MS * 2;

export function SchemaTree(props: SchemaTreeProps) {
const createDirectoryFeatureAvailable = useCreateDirectoryFeatureAvailable();
const {rootPath, rootName, rootType, currentPath, onActivePathUpdate} = props;
const dispatch = useTypedDispatch();
const input = useTypedSelector(selectUserInput);
const [getTableSchemaDataMutation] = tableSchemaDataApi.useGetTableSchemaDataMutation();

const getTableSchemaDataPromise = React.useCallback(
async (args: GetTableSchemaDataParams) => {
try {
const result = await Promise.race([
getTableSchemaDataMutation(args).unwrap(),
wait<undefined>(TABLE_SCHEMA_TIMEOUT),
]);
return result;
} catch (e) {
return undefined;
}
},
[getTableSchemaDataMutation],
);
const [
getTableSchemaDataQuery,
{currentData: actionsSchemaData, isFetching: isActionsDataFetching},
] = tableSchemaDataApi.useLazyGetTableSchemaDataQuery();

const [querySettings, setQueryExecutionSettings] = useQueryExecutionSettings();
const [createDirectoryOpen, setCreateDirectoryOpen] = React.useState(false);
Expand Down Expand Up @@ -123,6 +110,36 @@ export function SchemaTree(props: SchemaTreeProps) {
setParentPath(value);
setCreateDirectoryOpen(true);
};

const getTreeNodeActions = React.useMemo(() => {
return getActions(
dispatch,
{
setActivePath: onActivePathUpdate,
updateQueryExecutionSettings: (settings) =>
setQueryExecutionSettings({...querySettings, ...settings}),
showCreateDirectoryDialog: createDirectoryFeatureAvailable
? handleOpenCreateDirectoryDialog
: undefined,
getConfirmation: input ? getConfirmation : undefined,

schemaData: actionsSchemaData,
isSchemaDataLoading: isActionsDataFetching,
},
rootPath,
);
}, [
actionsSchemaData,
createDirectoryFeatureAvailable,
dispatch,
input,
isActionsDataFetching,
onActivePathUpdate,
querySettings,
rootPath,
setQueryExecutionSettings,
]);

return (
<React.Fragment>
<CreateDirectoryDialog
Expand All @@ -141,20 +158,15 @@ export function SchemaTree(props: SchemaTreeProps) {
collapsed: false,
}}
fetchPath={fetchPath}
getActions={getActions(
dispatch,
{
setActivePath: onActivePathUpdate,
updateQueryExecutionSettings: (settings) =>
setQueryExecutionSettings({...querySettings, ...settings}),
showCreateDirectoryDialog: createDirectoryFeatureAvailable
? handleOpenCreateDirectoryDialog
: undefined,
getTableSchemaDataPromise,
getConfirmation: input ? getConfirmation : undefined,
},
rootPath,
)}
getActions={getTreeNodeActions}
onActionsOpenToggle={({path, type, isOpen}) => {
const pathType = nodeTableTypeToPathType[type];
if (isOpen && pathType) {
getTableSchemaDataQuery({path, tenantName: rootPath, type: pathType});
}

return [];
}}
renderAdditionalNodeElements={getSchemaControls(dispatch, {
setActivePath: onActivePathUpdate,
})}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {Flex, Spin} from '@gravity-ui/uikit';
import copy from 'copy-to-clipboard';
import type {NavigationTreeNodeType, NavigationTreeProps} from 'ydb-ui-components';

import type {AppDispatch} from '../../../store';
import type {GetTableSchemaDataParams} from '../../../store/reducers/tableSchemaData';
import {TENANT_PAGES_IDS, TENANT_QUERY_TABS_ID} from '../../../store/reducers/tenant/constants';
import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
import type {QuerySettings} from '../../../types/store/query';
Expand All @@ -12,7 +12,6 @@ import {transformPath} from '../ObjectSummary/transformPath';
import type {SchemaData} from '../Schema/SchemaViewer/types';
import i18n from '../i18n';

import {nodeTableTypeToPathType} from './schema';
import type {TemplateFn} from './schemaQueryTemplates';
import {
addTableIndex,
Expand All @@ -36,14 +35,13 @@ import {
upsertQueryTemplate,
} from './schemaQueryTemplates';

interface ActionsAdditionalEffects {
interface ActionsAdditionalParams {
updateQueryExecutionSettings: (settings?: Partial<QuerySettings>) => void;
setActivePath: (path: string) => void;
showCreateDirectoryDialog?: (path: string) => void;
getTableSchemaDataPromise?: (
params: GetTableSchemaDataParams,
) => Promise<SchemaData[] | undefined>;
getConfirmation?: () => Promise<boolean>;
schemaData?: SchemaData[];
isSchemaDataLoading?: boolean;
}

interface BindActionParams {
Expand All @@ -56,32 +54,18 @@ interface BindActionParams {
const bindActions = (
params: BindActionParams,
dispatch: AppDispatch,
additionalEffects: ActionsAdditionalEffects,
additionalEffects: ActionsAdditionalParams,
) => {
const {setActivePath, showCreateDirectoryDialog, getTableSchemaDataPromise, getConfirmation} =
const {setActivePath, showCreateDirectoryDialog, getConfirmation, schemaData} =
additionalEffects;

const inputQuery = (tmpl: TemplateFn) => () => {
const applyInsert = () => {
const pathType = nodeTableTypeToPathType[params.type];
const withTableData = [selectQueryTemplate, upsertQueryTemplate].includes(tmpl);

const userInputDataPromise =
withTableData && pathType && getTableSchemaDataPromise
? getTableSchemaDataPromise({
path: params.path,
tenantName: params.tenantName,
type: pathType,
})
: Promise.resolve(undefined);

//order is important here: firstly we should open query tab and initialize editor (it will be set to window.ydbEditor), after that it is possible to insert snippet
dispatch(setTenantPage(TENANT_PAGES_IDS.query));
dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
setActivePath(params.path);
userInputDataPromise.then((tableData) => {
insertSnippetToEditor(tmpl({...params, tableData}));
});
insertSnippetToEditor(tmpl({...params, schemaData}));
};
if (getConfirmation) {
const confirmedPromise = getConfirmation();
Expand Down Expand Up @@ -142,8 +126,25 @@ const bindActions = (

type ActionsSet = ReturnType<Required<NavigationTreeProps>['getActions']>;

interface ActionConfig {
text: string;
action: () => void;
isLoading?: boolean;
}

const getActionWithLoader = ({text, action, isLoading}: ActionConfig) => ({
text: (
<Flex justifyContent="space-between" alignItems="center">
{text}
{isLoading && <Spin size="xs" />}
</Flex>
),
action,
disabled: isLoading,
});

export const getActions =
(dispatch: AppDispatch, additionalEffects: ActionsAdditionalEffects, rootPath = '') =>
(dispatch: AppDispatch, additionalEffects: ActionsAdditionalParams, rootPath = '') =>
(path: string, type: NavigationTreeNodeType) => {
const relativePath = transformPath(path, rootPath);
const actions = bindActions(
Expand Down Expand Up @@ -176,8 +177,16 @@ export const getActions =
[
{text: i18n('actions.alterTable'), action: actions.alterTable},
{text: i18n('actions.dropTable'), action: actions.dropTable},
{text: i18n('actions.selectQuery'), action: actions.selectQuery},
{text: i18n('actions.upsertQuery'), action: actions.upsertQuery},
getActionWithLoader({
text: i18n('actions.selectQuery'),
action: actions.selectQuery,
isLoading: additionalEffects.isSchemaDataLoading,
}),
getActionWithLoader({
text: i18n('actions.upsertQuery'),
action: actions.upsertQuery,
isLoading: additionalEffects.isSchemaDataLoading,
}),
{text: i18n('actions.addTableIndex'), action: actions.addTableIndex},
{text: i18n('actions.createCdcStream'), action: actions.createCdcStream},
],
Expand Down
8 changes: 4 additions & 4 deletions src/containers/Tenant/utils/schemaQueryTemplates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {SchemaData} from '../Schema/SchemaViewer/types';
export interface SchemaQueryParams {
path: string;
relativePath: string;
tableData?: SchemaData[];
schemaData?: SchemaData[];
}

export type TemplateFn = (params?: SchemaQueryParams) => string;
Expand Down Expand Up @@ -87,7 +87,7 @@ ALTER TABLE ${path}
export const selectQueryTemplate = (params?: SchemaQueryParams) => {
const path = params?.relativePath ? `\`${params?.relativePath}\`` : '${2:<my_table>}';
const columns =
params?.tableData?.map((column) => '`' + column.name + '`').join(', ') || '${1:*}';
params?.schemaData?.map((column) => '`' + column.name + '`').join(', ') || '${1:*}';
const filters = params?.relativePath ? '' : 'WHERE ${3:Key1 = 1}\nORDER BY ${4:Key1}\n';
return `SELECT ${columns}
FROM ${path}
Expand All @@ -96,8 +96,8 @@ ${filters}LIMIT \${5:10};`;
export const upsertQueryTemplate = (params?: SchemaQueryParams) => {
const path = params?.relativePath ? `\`${params?.relativePath}\`` : '${1:<my_table>}';
const columns =
params?.tableData?.map((column) => `\`${column.name}\``).join(', ') || '${2:id, name}';
const values = params?.tableData ? '${3: }' : '${3:1, "foo"}';
params?.schemaData?.map((column) => `\`${column.name}\``).join(', ') || '${2:id, name}';
const values = params?.schemaData ? '${3: }' : '${3:1, "foo"}';
return `UPSERT INTO ${path}
( ${columns} )
VALUES ( ${values} );`;
Expand Down
Loading
Loading