mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-03 04:46:27 +00:00
Fix(UI): Add service form bugs (#23613)
* Add default filter pattern fields for custom and share point drive connections * Add translations for additional properties * Fix the additional properties field showing in the default filters form Improve the additional properties field input in the form to make it clear with a label * Update generated TypeScript types * Empty commit * refactor(tests): streamline imports in Directory, File, Spreadsheet, and Worksheet class tests --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
1012247a7e
commit
ae39c7e68e
@ -28,6 +28,26 @@
|
||||
"title": "Connection Arguments",
|
||||
"$ref": "../connectionBasicType.json#/definitions/connectionArguments"
|
||||
},
|
||||
"directoryFilterPattern": {
|
||||
"title": "Default Directory Filter Pattern",
|
||||
"description": "Regex to only include/exclude directories that matches the pattern.",
|
||||
"$ref": "../../../../type/filterPattern.json#/definitions/filterPattern"
|
||||
},
|
||||
"fileFilterPattern": {
|
||||
"title": "Default File Filter Pattern",
|
||||
"description": "Regex to only include/exclude files that matches the pattern.",
|
||||
"$ref": "../../../../type/filterPattern.json#/definitions/filterPattern"
|
||||
},
|
||||
"spreadsheetFilterPattern": {
|
||||
"title": "Default Spreadsheet Filter Pattern",
|
||||
"description": "Regex to only include/exclude spreadsheets that matches the pattern.",
|
||||
"$ref": "../../../../type/filterPattern.json#/definitions/filterPattern"
|
||||
},
|
||||
"worksheetFilterPattern": {
|
||||
"title": "Default Worksheet Filter Pattern",
|
||||
"description": "Regex to only include/exclude worksheets that matches the pattern.",
|
||||
"$ref": "../../../../type/filterPattern.json#/definitions/filterPattern"
|
||||
},
|
||||
"supportsMetadataExtraction": {
|
||||
"title": "Supports Metadata Extraction",
|
||||
"$ref": "../connectionBasicType.json#/definitions/supportsMetadataExtraction"
|
||||
|
@ -61,6 +61,26 @@
|
||||
"title": "Connection Arguments",
|
||||
"$ref": "../connectionBasicType.json#/definitions/connectionArguments"
|
||||
},
|
||||
"directoryFilterPattern": {
|
||||
"title": "Default Directory Filter Pattern",
|
||||
"description": "Regex to only include/exclude directories that matches the pattern.",
|
||||
"$ref": "../../../../type/filterPattern.json#/definitions/filterPattern"
|
||||
},
|
||||
"fileFilterPattern": {
|
||||
"title": "Default File Filter Pattern",
|
||||
"description": "Regex to only include/exclude files that matches the pattern.",
|
||||
"$ref": "../../../../type/filterPattern.json#/definitions/filterPattern"
|
||||
},
|
||||
"spreadsheetFilterPattern": {
|
||||
"title": "Default Spreadsheet Filter Pattern",
|
||||
"description": "Regex to only include/exclude spreadsheets that matches the pattern.",
|
||||
"$ref": "../../../../type/filterPattern.json#/definitions/filterPattern"
|
||||
},
|
||||
"worksheetFilterPattern": {
|
||||
"title": "Default Worksheet Filter Pattern",
|
||||
"description": "Regex to only include/exclude worksheets that matches the pattern.",
|
||||
"$ref": "../../../../type/filterPattern.json#/definitions/filterPattern"
|
||||
},
|
||||
"supportsMetadataExtraction": {
|
||||
"title": "Supports Metadata Extraction",
|
||||
"$ref": "../connectionBasicType.json#/definitions/supportsMetadataExtraction"
|
||||
|
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright 2025 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { IChangeEvent } from '@rjsf/core';
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { LoadingState } from 'Models';
|
||||
import React from 'react';
|
||||
import { ServiceCategory } from '../../../../enums/service.enum';
|
||||
import { DatabaseServiceType } from '../../../../generated/entity/services/databaseService';
|
||||
import { ConfigData } from '../../../../interface/service.interface';
|
||||
import FiltersConfigForm from './FiltersConfigForm';
|
||||
import { FiltersConfigFormProps } from './FiltersConfigForm.interface';
|
||||
|
||||
jest.mock('../../../../hooks/useApplicationStore', () => ({
|
||||
useApplicationStore: jest.fn().mockReturnValue({
|
||||
inlineAlertDetails: undefined,
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../utils/JSONSchemaFormUtils', () => ({
|
||||
formatFormDataForSubmit: jest.fn((data) => data),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../utils/ServiceConnectionUtils', () => ({
|
||||
getConnectionSchemas: jest.fn().mockReturnValue({
|
||||
connSch: {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
filter1: { type: 'string' },
|
||||
filter2: { type: 'string' },
|
||||
someOtherProperty: { type: 'string' },
|
||||
},
|
||||
additionalProperties: true,
|
||||
},
|
||||
},
|
||||
validConfig: {},
|
||||
}),
|
||||
getFilteredSchema: jest.fn((properties) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { filter1, filter2, ...rest } = properties as Record<string, unknown>;
|
||||
|
||||
return rest;
|
||||
}),
|
||||
}));
|
||||
|
||||
const MockFormBuilder = React.forwardRef<
|
||||
unknown,
|
||||
{
|
||||
onSubmit: (data: IChangeEvent<ConfigData>) => void;
|
||||
onCancel: () => void;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
>(({ onSubmit, onCancel, children }, ref) => {
|
||||
React.useImperativeHandle(ref, () => ({}));
|
||||
|
||||
return (
|
||||
<div data-testid="form-builder">
|
||||
<button
|
||||
data-testid="submit-button"
|
||||
onClick={() => onSubmit({ formData: {} } as IChangeEvent<ConfigData>)}>
|
||||
Submit
|
||||
</button>
|
||||
<button data-testid="cancel-button" onClick={onCancel}>
|
||||
Cancel
|
||||
</button>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
jest.mock('../../../common/FormBuilder/FormBuilder', () => {
|
||||
return jest.fn().mockImplementation((props) => {
|
||||
return <MockFormBuilder {...props} />;
|
||||
});
|
||||
});
|
||||
|
||||
jest.mock('../../../common/InlineAlert/InlineAlert', () => {
|
||||
return jest
|
||||
.fn()
|
||||
.mockImplementation(() => <div data-testid="inline-alert">Alert</div>);
|
||||
});
|
||||
|
||||
const mockGetConnectionSchemas = jest.requireMock(
|
||||
'../../../../utils/ServiceConnectionUtils'
|
||||
).getConnectionSchemas;
|
||||
|
||||
const mockGetFilteredSchema = jest.requireMock(
|
||||
'../../../../utils/ServiceConnectionUtils'
|
||||
).getFilteredSchema;
|
||||
|
||||
const mockFormatFormDataForSubmit = jest.requireMock(
|
||||
'../../../../utils/JSONSchemaFormUtils'
|
||||
).formatFormDataForSubmit;
|
||||
|
||||
const mockUseApplicationStore = jest.requireMock(
|
||||
'../../../../hooks/useApplicationStore'
|
||||
).useApplicationStore;
|
||||
|
||||
describe('FiltersConfigForm', () => {
|
||||
const mockOnSave = jest.fn();
|
||||
const mockOnCancel = jest.fn();
|
||||
const mockOnFocus = jest.fn();
|
||||
|
||||
const defaultProps: FiltersConfigFormProps = {
|
||||
data: undefined,
|
||||
serviceType: DatabaseServiceType.Mysql,
|
||||
serviceCategory: ServiceCategory.DATABASE_SERVICES,
|
||||
status: 'initial' as LoadingState,
|
||||
onSave: mockOnSave,
|
||||
onCancel: mockOnCancel,
|
||||
onFocus: mockOnFocus,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Schema Filtering', () => {
|
||||
it('should remove filter properties from the schema', () => {
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
expect(mockGetFilteredSchema).toHaveBeenCalledWith(
|
||||
{
|
||||
filter1: { type: 'string' },
|
||||
filter2: { type: 'string' },
|
||||
someOtherProperty: { type: 'string' },
|
||||
},
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
it('should set additionalProperties to false in the filtered schema', () => {
|
||||
const mockFormBuilder = jest.requireMock(
|
||||
'../../../common/FormBuilder/FormBuilder'
|
||||
);
|
||||
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
const formBuilderCall = mockFormBuilder.mock.calls[0][0];
|
||||
|
||||
expect(formBuilderCall.schema.additionalProperties).toBe(false);
|
||||
});
|
||||
|
||||
it('should pass the filtered schema to FormBuilder', () => {
|
||||
const mockFormBuilder = jest.requireMock(
|
||||
'../../../common/FormBuilder/FormBuilder'
|
||||
);
|
||||
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
const formBuilderCall = mockFormBuilder.mock.calls[0][0];
|
||||
|
||||
expect(formBuilderCall.schema).toEqual({
|
||||
type: 'object',
|
||||
properties: {
|
||||
someOtherProperty: { type: 'string' },
|
||||
},
|
||||
additionalProperties: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Form Submission', () => {
|
||||
it('should format and save form data on submit', async () => {
|
||||
mockFormatFormDataForSubmit.mockReturnValue({ formatted: 'data' });
|
||||
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
const submitButton = screen.getByTestId('submit-button');
|
||||
fireEvent.click(submitButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockFormatFormDataForSubmit).toHaveBeenCalledWith({});
|
||||
expect(mockOnSave).toHaveBeenCalledWith({
|
||||
formData: { formatted: 'data' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should call onCancel when cancel button is clicked', () => {
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
const cancelButton = screen.getByTestId('cancel-button');
|
||||
fireEvent.click(cancelButton);
|
||||
|
||||
expect(mockOnCancel).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Empty Schema Handling', () => {
|
||||
it('should not show no config message with default mock (schema has properties)', () => {
|
||||
// Default mock has properties, so no-config message shouldn't show
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
expect(
|
||||
screen.queryByTestId('no-config-available')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show no config message when schema has properties', () => {
|
||||
mockGetFilteredSchema.mockReturnValue({
|
||||
someProperty: { type: 'string' },
|
||||
});
|
||||
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
expect(
|
||||
screen.queryByTestId('no-config-available')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Inline Alert', () => {
|
||||
it('should render inline alert when inlineAlertDetails is present', () => {
|
||||
mockUseApplicationStore.mockReturnValue({
|
||||
inlineAlertDetails: {
|
||||
type: 'error',
|
||||
message: 'Error message',
|
||||
},
|
||||
});
|
||||
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
expect(screen.getByTestId('inline-alert')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not render inline alert when inlineAlertDetails is undefined', () => {
|
||||
mockUseApplicationStore.mockReturnValue({
|
||||
inlineAlertDetails: undefined,
|
||||
});
|
||||
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
expect(screen.queryByTestId('inline-alert')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Props Handling', () => {
|
||||
it('should use custom okText and cancelText when provided', () => {
|
||||
const mockFormBuilder = jest.requireMock(
|
||||
'../../../common/FormBuilder/FormBuilder'
|
||||
);
|
||||
|
||||
render(
|
||||
<FiltersConfigForm
|
||||
{...defaultProps}
|
||||
cancelText="Custom Cancel"
|
||||
okText="Custom Save"
|
||||
/>
|
||||
);
|
||||
|
||||
const formBuilderCall = mockFormBuilder.mock.calls[0][0];
|
||||
|
||||
expect(formBuilderCall.okText).toBe('Custom Save');
|
||||
expect(formBuilderCall.cancelText).toBe('Custom Cancel');
|
||||
});
|
||||
|
||||
it('should use default okText and cancelText when not provided', () => {
|
||||
const mockFormBuilder = jest.requireMock(
|
||||
'../../../common/FormBuilder/FormBuilder'
|
||||
);
|
||||
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
const formBuilderCall = mockFormBuilder.mock.calls[0][0];
|
||||
|
||||
expect(formBuilderCall.okText).toBe('Save');
|
||||
expect(formBuilderCall.cancelText).toBe('Cancel');
|
||||
});
|
||||
|
||||
it('should pass all required props to FormBuilder', () => {
|
||||
const mockFormBuilder = jest.requireMock(
|
||||
'../../../common/FormBuilder/FormBuilder'
|
||||
);
|
||||
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
const formBuilderCall = mockFormBuilder.mock.calls[0][0];
|
||||
|
||||
expect(formBuilderCall.serviceCategory).toBe(
|
||||
ServiceCategory.DATABASE_SERVICES
|
||||
);
|
||||
expect(formBuilderCall.status).toBe('initial');
|
||||
expect(formBuilderCall.onFocus).toBe(mockOnFocus);
|
||||
expect(formBuilderCall.showFormHeader).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Connection Schema Integration', () => {
|
||||
it('should call getConnectionSchemas with correct parameters', () => {
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
expect(mockGetConnectionSchemas).toHaveBeenCalledWith({
|
||||
data: undefined,
|
||||
serviceCategory: ServiceCategory.DATABASE_SERVICES,
|
||||
serviceType: DatabaseServiceType.Mysql,
|
||||
});
|
||||
});
|
||||
|
||||
it('should use validConfig from getConnectionSchemas', () => {
|
||||
mockGetConnectionSchemas.mockReturnValue({
|
||||
connSch: {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
validConfig: { customConfig: 'value' },
|
||||
});
|
||||
|
||||
const mockFormBuilder = jest.requireMock(
|
||||
'../../../common/FormBuilder/FormBuilder'
|
||||
);
|
||||
|
||||
render(<FiltersConfigForm {...defaultProps} />);
|
||||
|
||||
const formBuilderCall = mockFormBuilder.mock.calls[0][0];
|
||||
|
||||
expect(formBuilderCall.formData).toEqual({ customConfig: 'value' });
|
||||
});
|
||||
});
|
||||
});
|
@ -69,6 +69,7 @@ function FiltersConfigForm({
|
||||
return {
|
||||
...connSch.schema,
|
||||
properties: propertiesWithoutFilters,
|
||||
additionalProperties: false, // Disable additional properties for default filters form
|
||||
};
|
||||
}, [connSch.schema.properties]);
|
||||
|
||||
|
@ -230,6 +230,14 @@ describe('ObjectFieldTemplate', () => {
|
||||
} as RJSFSchema,
|
||||
};
|
||||
|
||||
it('should render additional properties label when additionalProperties is true', () => {
|
||||
render(<ObjectFieldTemplate {...propsWithAdditional} />);
|
||||
|
||||
expect(
|
||||
screen.getByText('label.additional-property-plural')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render add button when additionalProperties is true', () => {
|
||||
render(<ObjectFieldTemplate {...propsWithAdditional} />);
|
||||
|
||||
@ -238,6 +246,14 @@ describe('ObjectFieldTemplate', () => {
|
||||
expect(addButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not render additional properties label when additionalProperties is false', () => {
|
||||
render(<ObjectFieldTemplate {...defaultProps} />);
|
||||
|
||||
expect(
|
||||
screen.queryByText('label.additional-property-plural')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not render add button when additionalProperties is false', () => {
|
||||
render(<ObjectFieldTemplate {...defaultProps} />);
|
||||
|
||||
|
@ -71,7 +71,7 @@ export const ObjectFieldTemplate: FunctionComponent<ObjectFieldTemplateProps> =
|
||||
|
||||
const fieldElement = (
|
||||
<Fragment>
|
||||
<Space className="w-full justify-between header-title-wrapper m-y-sm">
|
||||
<Space className="w-full justify-between header-title-wrapper m-t-sm">
|
||||
<label
|
||||
className={classNames('control-label', {
|
||||
'font-medium text-base-color text-md':
|
||||
@ -80,8 +80,16 @@ export const ObjectFieldTemplate: FunctionComponent<ObjectFieldTemplateProps> =
|
||||
id={`${idSchema.$id}__title`}>
|
||||
{title}
|
||||
</label>
|
||||
</Space>
|
||||
|
||||
{schema.additionalProperties && (
|
||||
<Space className="w-full justify-between m-t-sm">
|
||||
<label
|
||||
className="font-medium text-base-color text-md"
|
||||
id={`${idSchema.$id}__AdditionalProperties-label`}>
|
||||
{t('label.additional-property-plural')}
|
||||
</label>
|
||||
|
||||
{schema.additionalProperties && (
|
||||
<Button
|
||||
data-testid={`add-item-${title}`}
|
||||
icon={
|
||||
@ -99,8 +107,8 @@ export const ObjectFieldTemplate: FunctionComponent<ObjectFieldTemplateProps> =
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</Space>
|
||||
)}
|
||||
|
||||
{AdditionalField &&
|
||||
createElement(AdditionalField, {
|
||||
@ -119,7 +127,7 @@ export const ObjectFieldTemplate: FunctionComponent<ObjectFieldTemplateProps> =
|
||||
{!isEmpty(advancedProperties) && (
|
||||
<Collapse
|
||||
destroyInactivePanel
|
||||
className="advanced-properties-collapse m-y-sm"
|
||||
className="advanced-properties-collapse m-t-sm"
|
||||
expandIconPosition="end">
|
||||
<Panel header={`${title} ${t('label.advanced-config')}`} key="1">
|
||||
{advancedProperties.map((element, index) => (
|
||||
|
@ -14,16 +14,54 @@
|
||||
* Custom Drive Connection to build a source that is not supported.
|
||||
*/
|
||||
export interface CustomDriveConnection {
|
||||
connectionArguments?: { [key: string]: any };
|
||||
connectionOptions?: { [key: string]: string };
|
||||
connectionArguments?: { [key: string]: any };
|
||||
connectionOptions?: { [key: string]: string };
|
||||
/**
|
||||
* Regex to only include/exclude directories that matches the pattern.
|
||||
*/
|
||||
directoryFilterPattern?: FilterPattern;
|
||||
/**
|
||||
* Regex to only include/exclude files that matches the pattern.
|
||||
*/
|
||||
fileFilterPattern?: FilterPattern;
|
||||
/**
|
||||
* Regex to only include/exclude spreadsheets that matches the pattern.
|
||||
*/
|
||||
spreadsheetFilterPattern?: FilterPattern;
|
||||
supportsMetadataExtraction?: boolean;
|
||||
/**
|
||||
* Service Type
|
||||
*/
|
||||
type?: CustomDriveType;
|
||||
/**
|
||||
* Regex to only include/exclude worksheets that matches the pattern.
|
||||
*/
|
||||
worksheetFilterPattern?: FilterPattern;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regex to only include/exclude directories that matches the pattern.
|
||||
*
|
||||
* Regex to only fetch entities that matches the pattern.
|
||||
*
|
||||
* Regex to only include/exclude files that matches the pattern.
|
||||
*
|
||||
* Regex to only include/exclude spreadsheets that matches the pattern.
|
||||
*
|
||||
* Regex to only include/exclude worksheets that matches the pattern.
|
||||
*/
|
||||
export interface FilterPattern {
|
||||
/**
|
||||
* List of strings/regex patterns to match and exclude only database entities that match.
|
||||
*/
|
||||
excludes?: string[];
|
||||
/**
|
||||
* List of strings/regex patterns to match and include only database entities that match.
|
||||
*/
|
||||
includes?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Service Type
|
||||
*
|
||||
|
@ -24,10 +24,18 @@ export interface SharePointConnection {
|
||||
clientSecret: string;
|
||||
connectionArguments?: { [key: string]: any };
|
||||
connectionOptions?: { [key: string]: string };
|
||||
/**
|
||||
* Regex to only include/exclude directories that matches the pattern.
|
||||
*/
|
||||
directoryFilterPattern?: FilterPattern;
|
||||
/**
|
||||
* SharePoint drive ID. If not provided, default document library will be used
|
||||
*/
|
||||
driveId?: string;
|
||||
/**
|
||||
* Regex to only include/exclude files that matches the pattern.
|
||||
*/
|
||||
fileFilterPattern?: FilterPattern;
|
||||
/**
|
||||
* SharePoint site name
|
||||
*/
|
||||
@ -35,7 +43,11 @@ export interface SharePointConnection {
|
||||
/**
|
||||
* SharePoint site URL
|
||||
*/
|
||||
siteUrl: string;
|
||||
siteUrl: string;
|
||||
/**
|
||||
* Regex to only include/exclude spreadsheets that matches the pattern.
|
||||
*/
|
||||
spreadsheetFilterPattern?: FilterPattern;
|
||||
supportsMetadataExtraction?: boolean;
|
||||
/**
|
||||
* Directory (tenant) ID from Azure Active Directory
|
||||
@ -45,6 +57,32 @@ export interface SharePointConnection {
|
||||
* Service Type
|
||||
*/
|
||||
type?: SharePointType;
|
||||
/**
|
||||
* Regex to only include/exclude worksheets that matches the pattern.
|
||||
*/
|
||||
worksheetFilterPattern?: FilterPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regex to only include/exclude directories that matches the pattern.
|
||||
*
|
||||
* Regex to only fetch entities that matches the pattern.
|
||||
*
|
||||
* Regex to only include/exclude files that matches the pattern.
|
||||
*
|
||||
* Regex to only include/exclude spreadsheets that matches the pattern.
|
||||
*
|
||||
* Regex to only include/exclude worksheets that matches the pattern.
|
||||
*/
|
||||
export interface FilterPattern {
|
||||
/**
|
||||
* List of strings/regex patterns to match and exclude only database entities that match.
|
||||
*/
|
||||
excludes?: string[];
|
||||
/**
|
||||
* List of strings/regex patterns to match and include only database entities that match.
|
||||
*/
|
||||
includes?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "noch hinzugefügt",
|
||||
"adding-new-classification": "Neue Klassifizierung hinzufügen",
|
||||
"adding-new-tag": "Neuen Tag zu {{categoryName}} hinzufügen",
|
||||
"additional-property-plural": "Zusätzliche Eigenschaften",
|
||||
"address": "Adresse",
|
||||
"admin": "Administrator",
|
||||
"admin-plural": "Administratoren",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "added yet.",
|
||||
"adding-new-classification": "Adding New Classification",
|
||||
"adding-new-tag": "Adding new tag on {{categoryName}}",
|
||||
"additional-property-plural": "Additional Properties",
|
||||
"address": "Address",
|
||||
"admin": "Admin",
|
||||
"admin-plural": "Admins",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "aún no añadido.",
|
||||
"adding-new-classification": "Añadiendo nueva clasificación",
|
||||
"adding-new-tag": "Añadiendo una nueva etiqueta en {{categoryName}}",
|
||||
"additional-property-plural": "Propiedades Adicionales",
|
||||
"address": "Dirección",
|
||||
"admin": "Administrador",
|
||||
"admin-plural": "Administradores",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "encore ajouté",
|
||||
"adding-new-classification": "Ajouter une Nouvelle Classification",
|
||||
"adding-new-tag": "Ajouter une nouvelle balise à {{categoryName}}",
|
||||
"additional-property-plural": "Propriétés Additionnelles",
|
||||
"address": "Adresse",
|
||||
"admin": "Administrateur",
|
||||
"admin-plural": "Administrateurs",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "aínda engadido.",
|
||||
"adding-new-classification": "Engadindo unha nova clasificación",
|
||||
"adding-new-tag": "Engadindo unha nova etiqueta en {{categoryName}}",
|
||||
"additional-property-plural": "Propiedades Adicionales",
|
||||
"address": "Enderezo",
|
||||
"admin": "Administrador",
|
||||
"admin-plural": "Administradores",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "נוסף כעת",
|
||||
"adding-new-classification": "הוספת סיווג חדש",
|
||||
"adding-new-tag": "הוספת תג חדש ב- {{categoryName}}",
|
||||
"additional-property-plural": "מאפיינים נוספים",
|
||||
"address": "כתובת",
|
||||
"admin": "מנהל",
|
||||
"admin-plural": "מנהלים",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "未追加",
|
||||
"adding-new-classification": "新しい分類を追加",
|
||||
"adding-new-tag": "{{categoryName}}に新しいタグを追加",
|
||||
"additional-property-plural": "追加のプロパティ",
|
||||
"address": "アドレス",
|
||||
"admin": "管理者",
|
||||
"admin-plural": "管理者",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "아직 추가되지 않음.",
|
||||
"adding-new-classification": "새 분류 추가 중",
|
||||
"adding-new-tag": "{{categoryName}}에 새 태그 추가 중",
|
||||
"additional-property-plural": "추가 속성",
|
||||
"address": "주소",
|
||||
"admin": "관리자",
|
||||
"admin-plural": "관리자들",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "अजून जोडले.",
|
||||
"adding-new-classification": "नवीन वर्गीकरण जोडत आहे",
|
||||
"adding-new-tag": "{{categoryName}} वर नवीन टॅग जोडत आहे",
|
||||
"additional-property-plural": "अतिरिक्त गुणधर्म",
|
||||
"address": "पत्ता",
|
||||
"admin": "प्रशासक",
|
||||
"admin-plural": "प्रशासक",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "toch toegevoegd.",
|
||||
"adding-new-classification": "Nieuwe classificatie toevoegen",
|
||||
"adding-new-tag": "Toevoegen van nieuwe tag aan {{categoryName}}",
|
||||
"additional-property-plural": "Aanvullende eigenschappen",
|
||||
"address": "Adres",
|
||||
"admin": "Beheerder",
|
||||
"admin-plural": "Beheerders",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "هنوز اضافه نشده است.",
|
||||
"adding-new-classification": "اضافه کردن طبقهبندی جدید",
|
||||
"adding-new-tag": "اضافه کردن تگ جدید به {{categoryName }}",
|
||||
"additional-property-plural": "ویژگیهای اضافی",
|
||||
"address": "آدرس",
|
||||
"admin": "مدیر",
|
||||
"admin-plural": "مدیران",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "ainda não adicionado.",
|
||||
"adding-new-classification": "Adicionando Nova Classificação",
|
||||
"adding-new-tag": "Adicionando nova tag em {{categoryName}}",
|
||||
"additional-property-plural": "Propriedades Adicionais",
|
||||
"address": "Endereço",
|
||||
"admin": "Administrador",
|
||||
"admin-plural": "Administradores",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "ainda não adicionado.",
|
||||
"adding-new-classification": "Adicionando Nova Classificação",
|
||||
"adding-new-tag": "Adicionando nova tag em {{categoryName}}",
|
||||
"additional-property-plural": "Propriedades Adicionais",
|
||||
"address": "Endereço",
|
||||
"admin": "Admin",
|
||||
"admin-plural": "Admins",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "уже добавлено",
|
||||
"adding-new-classification": "Добавление новой классификации",
|
||||
"adding-new-tag": "Добавление нового тега {{categoryName}}",
|
||||
"additional-property-plural": "Дополнительные свойства",
|
||||
"address": "Адрес",
|
||||
"admin": "Админ",
|
||||
"admin-plural": "Админы",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "เพิ่มแล้ว.",
|
||||
"adding-new-classification": "กำลังเพิ่มการจำแนกประเภทใหม่",
|
||||
"adding-new-tag": "กำลังเพิ่มแท็กใหม่ที่ {{categoryName}}",
|
||||
"additional-property-plural": "คุณสมบัติเพิ่มเติม",
|
||||
"address": "ที่อยู่",
|
||||
"admin": "ผู้ดูแลระบบ",
|
||||
"admin-plural": "ผู้ดูแลระบบหลายคน",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "henüz eklendi.",
|
||||
"adding-new-classification": "Yeni Sınıflandırma Ekleniyor",
|
||||
"adding-new-tag": "{{categoryName}} üzerinde yeni etiket ekleniyor",
|
||||
"additional-property-plural": "Ekstra Özellikler",
|
||||
"address": "Adres",
|
||||
"admin": "Yönetici",
|
||||
"admin-plural": "Yöneticiler",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "已添加",
|
||||
"adding-new-classification": "正在添加新分类",
|
||||
"adding-new-tag": "正在添加新标签到{{categoryName}}",
|
||||
"additional-property-plural": "附加属性",
|
||||
"address": "地址",
|
||||
"admin": "管理员",
|
||||
"admin-plural": "管理员",
|
||||
|
@ -66,6 +66,7 @@
|
||||
"added-yet-lowercase": "尚未新增。",
|
||||
"adding-new-classification": "正在新增分類",
|
||||
"adding-new-tag": "在 {{categoryName}} 上新增標籤",
|
||||
"additional-property-plural": "附加屬性",
|
||||
"address": "地址",
|
||||
"admin": "管理員",
|
||||
"admin-plural": "管理員",
|
||||
|
@ -26,10 +26,8 @@ import { DetailPageWidgetKeys } from '../enums/CustomizeDetailPage.enum';
|
||||
import { EntityTabs } from '../enums/entity.enum';
|
||||
import { Directory } from '../generated/entity/data/directory';
|
||||
import { WidgetConfig } from '../pages/CustomizablePage/CustomizablePage.interface';
|
||||
import directoryClassBase, {
|
||||
DirectoryClassBase,
|
||||
DirectoryDetailPageTabProps,
|
||||
} from './DirectoryClassBase';
|
||||
import directoryClassBase, { DirectoryClassBase } from './DirectoryClassBase';
|
||||
import { DirectoryDetailPageTabProps } from './DirectoryDetailsUtils';
|
||||
|
||||
// Mock dependencies
|
||||
jest.mock('../constants/CustomizeWidgets.constants', () => ({
|
||||
|
@ -25,10 +25,8 @@ import { DetailPageWidgetKeys } from '../enums/CustomizeDetailPage.enum';
|
||||
import { EntityTabs } from '../enums/entity.enum';
|
||||
import { File } from '../generated/entity/data/file';
|
||||
import { WidgetConfig } from '../pages/CustomizablePage/CustomizablePage.interface';
|
||||
import fileClassBase, {
|
||||
FileClassBase,
|
||||
FileDetailPageTabProps,
|
||||
} from './FileClassBase';
|
||||
import fileClassBase, { FileClassBase } from './FileClassBase';
|
||||
import { FileDetailPageTabProps } from './FileDetailsUtils';
|
||||
|
||||
// Mock dependencies
|
||||
jest.mock('../constants/CustomizeWidgets.constants', () => ({
|
||||
|
@ -28,8 +28,8 @@ import { Spreadsheet } from '../generated/entity/data/spreadsheet';
|
||||
import { WidgetConfig } from '../pages/CustomizablePage/CustomizablePage.interface';
|
||||
import spreadsheetClassBase, {
|
||||
SpreadsheetClassBase,
|
||||
SpreadsheetDetailPageTabProps,
|
||||
} from './SpreadsheetClassBase';
|
||||
import { SpreadsheetDetailPageTabProps } from './SpreadsheetDetailsUtils';
|
||||
|
||||
// Mock dependencies
|
||||
jest.mock('../constants/CustomizeWidgets.constants', () => ({
|
||||
|
@ -26,10 +26,8 @@ import { DetailPageWidgetKeys } from '../enums/CustomizeDetailPage.enum';
|
||||
import { EntityTabs } from '../enums/entity.enum';
|
||||
import { Worksheet } from '../generated/entity/data/worksheet';
|
||||
import { WidgetConfig } from '../pages/CustomizablePage/CustomizablePage.interface';
|
||||
import worksheetClassBase, {
|
||||
WorksheetClassBase,
|
||||
WorksheetDetailPageTabProps,
|
||||
} from './WorksheetClassBase';
|
||||
import worksheetClassBase, { WorksheetClassBase } from './WorksheetClassBase';
|
||||
import { WorksheetDetailPageTabProps } from './WorksheetDetailsUtils';
|
||||
|
||||
// Mock dependencies
|
||||
jest.mock('../constants/CustomizeWidgets.constants', () => ({
|
||||
|
Loading…
x
Reference in New Issue
Block a user