Skip to content

Commit

Permalink
feat: indicate schema description loading (#1672)
Browse files Browse the repository at this point in the history
Co-authored-by: Anton Standrik <[email protected]>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 22, 2024
1 parent 7302a4a commit c0781f1
Show file tree
Hide file tree
Showing 14 changed files with 222 additions and 115 deletions.
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

0 comments on commit c0781f1

Please sign in to comment.