mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-01 19:18:05 +00:00
This reverts commit e32f9cf8623cbe96cce8d0cc6c063b489c3f9590.
This commit is contained in:
parent
e1f717ad08
commit
3ff11d8518
@ -120,6 +120,7 @@
|
||||
"react-quill-new": "^3.3.2",
|
||||
"react-reflex": "^4.0.12",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-toastify": "^8.2.0",
|
||||
"reactflow": "^11.10.2",
|
||||
"reactjs-localstorage": "^1.0.1",
|
||||
"recharts": "2.10.3",
|
||||
|
||||
@ -363,15 +363,13 @@ test.describe('Activity feed', () => {
|
||||
await page.getByText('OK').click();
|
||||
await resolveTask;
|
||||
|
||||
await toastNotification(page, /Task resolved successfully/, 'success');
|
||||
await toastNotification(page, /Task resolved successfully/);
|
||||
|
||||
// Task 1 - Resolved the task
|
||||
|
||||
const resolveTask2 = page.waitForResponse('/api/v1/feed/tasks/*/resolve');
|
||||
await page.getByText('Accept Suggestion').click();
|
||||
await resolveTask2;
|
||||
|
||||
await toastNotification(page, /Task resolved successfully/, 'success');
|
||||
await toastNotification(page, /Task resolved successfully/);
|
||||
|
||||
await checkTaskCount(page, 0, 2);
|
||||
});
|
||||
@ -414,11 +412,7 @@ test.describe('Activity feed', () => {
|
||||
|
||||
await page.getByRole('menuitem', { name: 'close' }).click();
|
||||
|
||||
await toastNotification(
|
||||
page,
|
||||
'Task cannot be closed without a comment.',
|
||||
'error'
|
||||
);
|
||||
await toastNotification(page, 'Task cannot be closed without a comment.');
|
||||
|
||||
// Close the task from the Button.Group, with comment is added.
|
||||
await page.fill(
|
||||
@ -677,8 +671,7 @@ base.describe('Activity feed with Data Consumer User', () => {
|
||||
// await toastNotification(page1, 'Task closed successfully.');
|
||||
await toastNotification(
|
||||
page1,
|
||||
'An exception with message [Cannot invoke "java.util.List.stream()" because "owners" is null] was thrown while processing request.',
|
||||
'error'
|
||||
'An exception with message [Cannot invoke "java.util.List.stream()" because "owners" is null] was thrown while processing request.'
|
||||
);
|
||||
|
||||
// TODO: Ashish - Enable them once issue is resolved from Backend https://github.com/open-metadata/OpenMetadata/issues/17059
|
||||
@ -991,8 +984,7 @@ base.describe('Activity feed with Data Consumer User', () => {
|
||||
await toastNotification(
|
||||
page2,
|
||||
// eslint-disable-next-line max-len
|
||||
`Principal: CatalogPrincipal{name='${viewAllUser.responseData.name}'} operation EditDescription denied by role ${viewAllRoles.responseData.name}, policy ${viewAllPolicy.responseData.name}, rule editNotAllowed`,
|
||||
'error'
|
||||
`Principal: CatalogPrincipal{name='${viewAllUser.responseData.name}'} operation EditDescription denied by role ${viewAllRoles.responseData.name}, policy ${viewAllPolicy.responseData.name}, rule editNotAllowed`
|
||||
);
|
||||
|
||||
await afterActionUser2();
|
||||
|
||||
@ -118,8 +118,7 @@ test.describe('Teams drag and drop should work properly', () => {
|
||||
await dragAndDropElement(page, team, teamNameGroup);
|
||||
await toastNotification(
|
||||
page,
|
||||
`You cannot move to this team as Team Type ${TEAM_TYPE_BY_NAME[team]} can't be Group children`,
|
||||
'error'
|
||||
`You cannot move to this team as Team Type ${TEAM_TYPE_BY_NAME[team]} can't be Group children`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -133,8 +132,7 @@ test.describe('Teams drag and drop should work properly', () => {
|
||||
await dragAndDropElement(page, team, teamNameDepartment);
|
||||
await toastNotification(
|
||||
page,
|
||||
`You cannot move to this team as Team Type ${TEAM_TYPE_BY_NAME[team]} can't be Department children`,
|
||||
'error'
|
||||
`You cannot move to this team as Team Type ${TEAM_TYPE_BY_NAME[team]} can't be Department children`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -145,8 +143,7 @@ test.describe('Teams drag and drop should work properly', () => {
|
||||
await dragAndDropElement(page, teamNameBusiness, teamNameDivision);
|
||||
await toastNotification(
|
||||
page,
|
||||
"You cannot move to this team as Team Type BusinessUnit can't be Division children",
|
||||
'error'
|
||||
"You cannot move to this team as Team Type BusinessUnit can't be Division children"
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -12,12 +12,7 @@
|
||||
*/
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { GlobalSettingOptions } from '../../constant/settings';
|
||||
import {
|
||||
descriptionBox,
|
||||
redirectToHomePage,
|
||||
toastNotification,
|
||||
uuid,
|
||||
} from '../../utils/common';
|
||||
import { descriptionBox, redirectToHomePage, uuid } from '../../utils/common';
|
||||
import { settingClick } from '../../utils/sidebar';
|
||||
|
||||
const apiServiceConfig = {
|
||||
@ -94,6 +89,10 @@ test.describe('API service', () => {
|
||||
|
||||
await deleteResponse;
|
||||
|
||||
await toastNotification(page, /deleted successfully!/);
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
/deleted successfully!/
|
||||
);
|
||||
|
||||
await page.click('.Toastify__close-button');
|
||||
});
|
||||
});
|
||||
|
||||
@ -84,11 +84,7 @@ test.describe('Domains', () => {
|
||||
await deleteRes;
|
||||
|
||||
await expect(
|
||||
page.getByText(
|
||||
`"${
|
||||
domain.data.displayName ?? domain.data.name
|
||||
}" deleted successfully!`
|
||||
)
|
||||
page.getByText(`"${domain.data.displayName}" deleted`)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
|
||||
@ -378,8 +378,7 @@ test.describe('Glossary tests', () => {
|
||||
|
||||
await toastNotification(
|
||||
page,
|
||||
/mutually exclusive and can't be assigned together/,
|
||||
'error'
|
||||
/mutually exclusive and can't be assigned together/
|
||||
);
|
||||
|
||||
// Add non mutually exclusive tags
|
||||
|
||||
@ -25,11 +25,7 @@ import {
|
||||
UPDATED_RULE_NAME,
|
||||
} from '../../constant/permission';
|
||||
import { GlobalSettingOptions } from '../../constant/settings';
|
||||
import {
|
||||
descriptionBox,
|
||||
redirectToHomePage,
|
||||
toastNotification,
|
||||
} from '../../utils/common';
|
||||
import { descriptionBox, redirectToHomePage } from '../../utils/common';
|
||||
import { validateFormNameFieldInput } from '../../utils/form';
|
||||
import { settingClick } from '../../utils/sidebar';
|
||||
|
||||
@ -262,10 +258,8 @@ test.describe('Policy page should work properly', () => {
|
||||
await page.locator('[data-testid="delete-rule"]').click();
|
||||
|
||||
// Validate the error message
|
||||
await toastNotification(
|
||||
page,
|
||||
ERROR_MESSAGE_VALIDATION.lastRuleCannotBeRemoved,
|
||||
'error'
|
||||
await expect(page.locator('.Toastify__toast-body')).toContainText(
|
||||
ERROR_MESSAGE_VALIDATION.lastRuleCannotBeRemoved
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -12,12 +12,7 @@
|
||||
*/
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { GlobalSettingOptions } from '../../constant/settings';
|
||||
import {
|
||||
descriptionBox,
|
||||
redirectToHomePage,
|
||||
toastNotification,
|
||||
uuid,
|
||||
} from '../../utils/common';
|
||||
import { descriptionBox, redirectToHomePage, uuid } from '../../utils/common';
|
||||
import { removePolicyFromRole } from '../../utils/roles';
|
||||
import { settingClick } from '../../utils/sidebar';
|
||||
|
||||
@ -206,12 +201,9 @@ test('Roles page should work properly', async ({ page }) => {
|
||||
// Removing the last policy and validating the error message
|
||||
await removePolicyFromRole(page, policies.dataConsumerPolicy, roleName);
|
||||
|
||||
await toastNotification(
|
||||
page,
|
||||
errorMessageValidation.lastPolicyCannotBeRemoved,
|
||||
'error'
|
||||
await expect(page.locator('.Toastify__toast-body')).toContainText(
|
||||
errorMessageValidation.lastPolicyCannotBeRemoved
|
||||
);
|
||||
|
||||
await expect(page.locator('.ant-table-row')).toContainText(
|
||||
policies.dataConsumerPolicy
|
||||
);
|
||||
|
||||
@ -16,7 +16,6 @@ import {
|
||||
descriptionBox,
|
||||
getApiContext,
|
||||
redirectToHomePage,
|
||||
toastNotification,
|
||||
} from '../../utils/common';
|
||||
import { deleteTestCase, visitDataQualityTab } from '../../utils/testCases';
|
||||
|
||||
@ -134,7 +133,11 @@ test('Table difference test case', async ({ page }) => {
|
||||
await page.getByTitle('name', { exact: true }).click();
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
await toastNotification(page, 'Test case updated successfully.');
|
||||
await expect(page.getByRole('alert')).toContainText(
|
||||
'Test case updated successfully.'
|
||||
);
|
||||
|
||||
await page.getByLabel('close', { exact: true }).click();
|
||||
});
|
||||
|
||||
await test.step('Delete', async () => {
|
||||
@ -230,7 +233,11 @@ test('Custom SQL Query', async ({ page }) => {
|
||||
await page.getByPlaceholder('Enter a Threshold').fill('244');
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
await toastNotification(page, 'Test case updated successfully.');
|
||||
await expect(page.getByRole('alert')).toContainText(
|
||||
'Test case updated successfully.'
|
||||
);
|
||||
|
||||
await page.getByLabel('close', { exact: true }).click();
|
||||
});
|
||||
|
||||
await test.step('Delete', async () => {
|
||||
@ -327,7 +334,11 @@ test('Column Values To Be Not Null', async ({ page }) => {
|
||||
await page.keyboard.type(' update');
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
await toastNotification(page, 'Test case updated successfully.');
|
||||
await expect(page.getByRole('alert')).toContainText(
|
||||
'Test case updated successfully.'
|
||||
);
|
||||
|
||||
await page.getByLabel('close', { exact: true }).click();
|
||||
});
|
||||
|
||||
await test.step('Delete', async () => {
|
||||
|
||||
@ -22,11 +22,7 @@ import { SearchIndexClass } from '../../support/entity/SearchIndexClass';
|
||||
import { StoredProcedureClass } from '../../support/entity/StoredProcedureClass';
|
||||
import { TableClass } from '../../support/entity/TableClass';
|
||||
import { TopicClass } from '../../support/entity/TopicClass';
|
||||
import {
|
||||
createNewPage,
|
||||
redirectToHomePage,
|
||||
toastNotification,
|
||||
} from '../../utils/common';
|
||||
import { createNewPage, redirectToHomePage } from '../../utils/common';
|
||||
import { addMultiOwner, assignTier } from '../../utils/entity';
|
||||
|
||||
const entities = [
|
||||
@ -237,7 +233,11 @@ entities.forEach((EntityClass) => {
|
||||
|
||||
await deleteResponse;
|
||||
|
||||
await toastNotification(page, /deleted successfully!/);
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
/deleted successfully!/
|
||||
);
|
||||
|
||||
await page.click('.Toastify__close-button');
|
||||
|
||||
await page.reload();
|
||||
|
||||
|
||||
@ -23,11 +23,7 @@ import { MlmodelServiceClass } from '../../support/entity/service/MlmodelService
|
||||
import { PipelineServiceClass } from '../../support/entity/service/PipelineServiceClass';
|
||||
import { SearchIndexServiceClass } from '../../support/entity/service/SearchIndexServiceClass';
|
||||
import { StorageServiceClass } from '../../support/entity/service/StorageServiceClass';
|
||||
import {
|
||||
createNewPage,
|
||||
redirectToHomePage,
|
||||
toastNotification,
|
||||
} from '../../utils/common';
|
||||
import { createNewPage, redirectToHomePage } from '../../utils/common';
|
||||
import { addMultiOwner, assignTier } from '../../utils/entity';
|
||||
|
||||
const entities = [
|
||||
@ -202,7 +198,11 @@ entities.forEach((EntityClass) => {
|
||||
|
||||
await deleteResponse;
|
||||
|
||||
await toastNotification(page, /deleted successfully!/);
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
/deleted successfully!/
|
||||
);
|
||||
|
||||
await page.click('.Toastify__close-button');
|
||||
|
||||
await page.reload();
|
||||
|
||||
|
||||
@ -113,14 +113,15 @@ export const getEntityTypeSearchIndexMapping = (entityType: string) => {
|
||||
|
||||
export const toastNotification = async (
|
||||
page: Page,
|
||||
message: string | RegExp,
|
||||
type: 'info' | 'success' | 'warning' | 'error' = 'success'
|
||||
message: string | RegExp
|
||||
) => {
|
||||
await expect(page.locator(`.alert-container.${type}`)).toHaveText(message);
|
||||
await expect(page.getByRole('alert').first()).toHaveText(message);
|
||||
|
||||
await expect(page.locator('.ant-alert-icon')).toBeVisible();
|
||||
|
||||
await expect(page.locator('.alert-container button')).toBeVisible();
|
||||
await page
|
||||
.locator('.Toastify__toast')
|
||||
.getByLabel('close', { exact: true })
|
||||
.first()
|
||||
.click();
|
||||
};
|
||||
|
||||
export const clickOutside = async (page: Page) => {
|
||||
|
||||
@ -16,7 +16,6 @@ import {
|
||||
NAME_MAX_LENGTH_VALIDATION_ERROR,
|
||||
NAME_VALIDATION_ERROR,
|
||||
} from '../constant/common';
|
||||
import { toastNotification } from './common';
|
||||
|
||||
type CustomMetricDetails = {
|
||||
page: Page;
|
||||
@ -119,11 +118,12 @@ export const createCustomMetric = async ({
|
||||
await page.click('[data-testid="submit-button"]');
|
||||
await createMetricResponse;
|
||||
|
||||
await toastNotification(
|
||||
page,
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
new RegExp(`${metric.name} created successfully.`)
|
||||
);
|
||||
|
||||
await page.locator('.Toastify__close-button').click();
|
||||
|
||||
// verify the created custom metric
|
||||
await expect(page).toHaveURL(/profiler/);
|
||||
await expect(
|
||||
|
||||
@ -24,7 +24,7 @@ import {
|
||||
} from '../constant/delete';
|
||||
import { ES_RESERVED_CHARACTERS } from '../constant/entity';
|
||||
import { EntityTypeEndpoint } from '../support/entity/Entity.interface';
|
||||
import { clickOutside, redirectToHomePage, toastNotification } from './common';
|
||||
import { clickOutside, redirectToHomePage } from './common';
|
||||
|
||||
export const visitEntityPage = async (data: {
|
||||
page: Page;
|
||||
@ -789,6 +789,7 @@ const announcementForm = async (
|
||||
);
|
||||
await page.click('#announcement-submit');
|
||||
await announcementSubmit;
|
||||
await page.click('.Toastify__close-button');
|
||||
};
|
||||
|
||||
export const createAnnouncement = async (
|
||||
@ -1178,7 +1179,11 @@ export const restoreEntity = async (page: Page) => {
|
||||
await page.click('[data-testid="restore-button"]');
|
||||
await page.click('button:has-text("Restore")');
|
||||
|
||||
await toastNotification(page, /restored successfully/);
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
/restored successfully/
|
||||
);
|
||||
|
||||
await page.click('.Toastify__close-button');
|
||||
|
||||
const exists = await page
|
||||
.locator('[data-testid="deleted-badge"]')
|
||||
@ -1217,7 +1222,11 @@ export const softDeleteEntity = async (
|
||||
|
||||
await deleteResponse;
|
||||
|
||||
await toastNotification(page, /deleted successfully!/);
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
/deleted successfully!/
|
||||
);
|
||||
|
||||
await page.click('.Toastify__close-button');
|
||||
|
||||
await page.reload();
|
||||
|
||||
@ -1282,7 +1291,11 @@ export const hardDeleteEntity = async (
|
||||
await page.click('[data-testid="confirm-button"]');
|
||||
await deleteResponse;
|
||||
|
||||
await toastNotification(page, /deleted successfully!/);
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
/deleted successfully!/
|
||||
);
|
||||
|
||||
await page.click('.Toastify__close-button');
|
||||
};
|
||||
|
||||
export const checkDataAssetWidget = async (
|
||||
|
||||
@ -63,9 +63,9 @@ export const LINEAGE_CSV_HEADERS = [
|
||||
|
||||
export const verifyColumnLayerInactive = async (page: Page) => {
|
||||
await page.click('[data-testid="lineage-layer-btn"]'); // Open Layer popover
|
||||
|
||||
await expect(page.getByTestId('lineage-layer-column-btn')).not.toBeFocused;
|
||||
|
||||
await page.waitForSelector(
|
||||
'[data-testid="lineage-layer-column-btn"]:not(.active)'
|
||||
);
|
||||
await page.click('[data-testid="lineage-layer-btn"]'); // Close Layer popover
|
||||
};
|
||||
|
||||
|
||||
@ -138,7 +138,11 @@ export const softDeleteUserProfilePage = async (
|
||||
|
||||
await deleteResponse;
|
||||
|
||||
await toastNotification(page, /deleted successfully!/);
|
||||
await expect(page.locator('.Toastify__toast-body')).toHaveText(
|
||||
/deleted successfully!/
|
||||
);
|
||||
|
||||
await page.click('.Toastify__close-button');
|
||||
|
||||
await deletedUserChecks(page);
|
||||
};
|
||||
@ -715,8 +719,7 @@ const resetPasswordModal = async (
|
||||
page,
|
||||
isOldPasswordCorrect
|
||||
? 'Password updated successfully.'
|
||||
: 'Old Password is not correct',
|
||||
isOldPasswordCorrect ? 'success' : 'error'
|
||||
: 'Old Password is not correct'
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -16,12 +16,15 @@ import React, { FC, useEffect } from 'react';
|
||||
import { HelmetProvider } from 'react-helmet-async';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import { Router } from 'react-router-dom';
|
||||
import { ToastContainer } from 'react-toastify';
|
||||
import 'react-toastify/dist/ReactToastify.min.css';
|
||||
import AppRouter from './components/AppRouter/AppRouter';
|
||||
import { AuthProvider } from './components/Auth/AuthProviders/AuthProvider';
|
||||
import ErrorBoundary from './components/common/ErrorBoundary/ErrorBoundary';
|
||||
import { EntityExportModalProvider } from './components/Entity/EntityExportModalProvider/EntityExportModalProvider.component';
|
||||
import ApplicationsProvider from './components/Settings/Applications/ApplicationsProvider/ApplicationsProvider';
|
||||
import WebAnalyticsProvider from './components/WebAnalytics/WebAnalyticsProvider';
|
||||
import { TOAST_OPTIONS } from './constants/Toasts.constants';
|
||||
import AntDConfigProvider from './context/AntDConfigProvider/AntDConfigProvider';
|
||||
import PermissionProvider from './context/PermissionProvider/PermissionProvider';
|
||||
import TourProvider from './context/TourProvider/TourProvider';
|
||||
@ -95,6 +98,7 @@ const App: FC = () => {
|
||||
</ErrorBoundary>
|
||||
</I18nextProvider>
|
||||
</Router>
|
||||
<ToastContainer {...TOAST_OPTIONS} newestOnTop />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
<svg width="14" height="15" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14 1.91L12.59 0.5L7 6.09L1.41 0.5L0 1.91L5.59 7.5L0 13.09L1.41 14.5L7 8.91L12.59 14.5L14 13.09L8.41 7.5L14 1.91Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 249 B |
@ -1,12 +0,0 @@
|
||||
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_6713_202785)">
|
||||
<path d="M6.28843 0L0 6.28843V18.7116L6.28843 25H18.7116L25 18.7116V6.28843L18.7116 0L6.28843 0ZM23.5352 18.1048L18.1048 23.5352H6.89517L1.46484 18.1048V6.89517L6.89517 1.46484H18.1048L23.5352 6.89517V18.1048Z" fill="currentColor"/>
|
||||
<path d="M12.5 14.428C11.9606 14.428 11.5234 13.9908 11.5234 13.4514V7.59204C11.5234 7.05269 11.9606 6.61548 12.5 6.61548C13.0394 6.61548 13.4766 7.05269 13.4766 7.59204V13.4514C13.4766 13.9908 13.0394 14.428 12.5 14.428Z" fill="currentColor"/>
|
||||
<path d="M12.5 18.3342C13.0393 18.3342 13.4766 17.897 13.4766 17.3577C13.4766 16.8183 13.0393 16.3811 12.5 16.3811C11.9607 16.3811 11.5234 16.8183 11.5234 17.3577C11.5234 17.897 11.9607 18.3342 12.5 18.3342Z" fill="currentColor"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_6713_202785">
|
||||
<rect width="25" height="25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 962 B |
@ -1,12 +0,0 @@
|
||||
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_6713_202773)">
|
||||
<path d="M12.5 0C5.59126 0 0 5.59063 0 12.5C0 19.4086 5.59063 25 12.5 25C19.4087 25 25 19.4094 25 12.5C25 5.59136 19.4094 0 12.5 0ZM12.5 23.2558C6.56924 23.2558 1.74419 18.4308 1.74419 12.5C1.74419 6.56919 6.56924 1.74419 12.5 1.74419C18.4308 1.74419 23.2558 6.56919 23.2558 12.5C23.2558 18.4308 18.4308 23.2558 12.5 23.2558Z" fill="currentColor"/>
|
||||
<path d="M12.5003 10.4197C11.7599 10.4197 11.2334 10.7324 11.2334 11.1931V17.4619C11.2334 17.8568 11.7599 18.2517 12.5003 18.2517C13.2079 18.2517 13.7837 17.8568 13.7837 17.4619V11.193C13.7837 10.7323 13.2079 10.4197 12.5003 10.4197Z" fill="currentColor"/>
|
||||
<path d="M12.5005 6.55322C11.7437 6.55322 11.1514 7.09619 11.1514 7.72144C11.1514 8.34673 11.7437 8.90615 12.5005 8.90615C13.241 8.90615 13.8333 8.34673 13.8333 7.72144C13.8333 7.09619 13.2409 6.55322 12.5005 6.55322Z" fill="currentColor"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_6713_202773">
|
||||
<rect width="25" height="25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@ -1,10 +0,0 @@
|
||||
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_6713_202783)">
|
||||
<path d="M18.0256 8.53367C18.4071 8.91514 18.4071 9.5335 18.0256 9.91478L11.4742 16.4663C11.0928 16.8476 10.4746 16.8476 10.0931 16.4663L6.97441 13.3474C6.59294 12.9662 6.59294 12.3478 6.97441 11.9665C7.35569 11.585 7.97405 11.585 8.35533 11.9665L10.7836 14.3948L16.6445 8.53367C17.0259 8.15239 17.6443 8.15239 18.0256 8.53367ZM25 12.5C25 19.4094 19.4084 25 12.5 25C5.59063 25 0 19.4084 0 12.5C0 5.59063 5.59158 0 12.5 0C19.4094 0 25 5.59158 25 12.5ZM23.0469 12.5C23.0469 6.67019 18.329 1.95312 12.5 1.95312C6.67019 1.95312 1.95312 6.67095 1.95312 12.5C1.95312 18.3298 6.67095 23.0469 12.5 23.0469C18.3298 23.0469 23.0469 18.329 23.0469 12.5Z" fill="currentColor"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_6713_202783">
|
||||
<rect width="25" height="25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 919 B |
@ -1,12 +0,0 @@
|
||||
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_6713_202641)">
|
||||
<path d="M21.0938 24.2171H3.90625C1.75234 24.2171 0 22.4648 0 20.3109C0 19.6424 0.171973 18.9826 0.497461 18.4023L9.08911 2.78097C9.09062 2.77823 9.09214 2.77555 9.09365 2.77281C10.5859 0.119837 14.4135 0.11886 15.9064 2.77281C15.9079 2.7755 15.9094 2.77823 15.9109 2.78097L24.5026 18.4022C24.828 18.9825 25 19.6424 25 20.3109C25 22.4648 23.2477 24.2171 21.0938 24.2171ZM10.798 3.72667L2.20674 19.3472C2.20522 19.35 2.20371 19.3527 2.2022 19.3554C2.03926 19.645 1.95312 19.9755 1.95312 20.3109C1.95312 21.3878 2.8293 22.264 3.90625 22.264H21.0938C22.1707 22.264 23.0469 21.3878 23.0469 20.3109C23.0469 19.9754 22.9607 19.645 22.7978 19.3554C22.7963 19.3527 22.7948 19.35 22.7933 19.3472L14.2021 3.72692C13.4545 2.40426 11.5465 2.40275 10.798 3.72667Z" fill="currentColor"/>
|
||||
<path d="M12.5 15.428C11.9606 15.428 11.5234 14.9908 11.5234 14.4514V8.59204C11.5234 8.05269 11.9606 7.61548 12.5 7.61548C13.0394 7.61548 13.4766 8.05269 13.4766 8.59204V14.4514C13.4766 14.9908 13.0394 15.428 12.5 15.428Z" fill="currentColor"/>
|
||||
<path d="M12.5 19.3342C13.0393 19.3342 13.4766 18.897 13.4766 18.3577C13.4766 17.8183 13.0393 17.3811 12.5 17.3811C11.9607 17.3811 11.5234 17.8183 11.5234 18.3577C11.5234 18.897 11.9607 19.3342 12.5 19.3342Z" fill="currentColor"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_6713_202641">
|
||||
<rect width="25" height="25" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 { Alert } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import React, { useMemo } from 'react';
|
||||
import { ReactComponent as CrossIcon } from '../../assets/svg/ic-cross.svg';
|
||||
import { useAlertStore } from '../../hooks/useAlertStore';
|
||||
import { getIconAndClassName } from '../../utils/ToastUtils';
|
||||
import './alert-bar.style.less';
|
||||
import { AlertBarProps } from './AlertBar.interface';
|
||||
|
||||
const AlertBar = ({ type, message }: AlertBarProps): JSX.Element => {
|
||||
const { resetAlert, animationClass } = useAlertStore();
|
||||
|
||||
const { icon: AlertIcon, className } = useMemo(() => {
|
||||
return getIconAndClassName(type);
|
||||
}, [type]);
|
||||
|
||||
return (
|
||||
<Alert
|
||||
closable
|
||||
showIcon
|
||||
afterClose={resetAlert}
|
||||
className={classNames(className, 'alert-container', animationClass)}
|
||||
closeIcon={<CrossIcon color="currentColor" />}
|
||||
description={message}
|
||||
icon={AlertIcon && <AlertIcon />}
|
||||
type={type}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default AlertBar;
|
||||
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 (reference) url('../../styles/variables.less');
|
||||
|
||||
@keyframes resize-show-animation {
|
||||
from {
|
||||
height: 0;
|
||||
padding: 0 20px;
|
||||
}
|
||||
to {
|
||||
height: 64px;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes resize-hide-animation {
|
||||
from {
|
||||
height: 64px;
|
||||
padding: 20px;
|
||||
}
|
||||
to {
|
||||
height: 0;
|
||||
padding: 0 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.alert-container {
|
||||
overflow-y: scroll;
|
||||
backdrop-filter: blur(500px);
|
||||
|
||||
&.show-alert {
|
||||
animation: resize-show-animation 1.2s ease-in-out forwards;
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
z-index: 20;
|
||||
width: 96%;
|
||||
}
|
||||
|
||||
&.hide-alert {
|
||||
animation: resize-hide-animation 1.2s ease-in-out forwards;
|
||||
}
|
||||
|
||||
&.info {
|
||||
background-color: @info-bg-color;
|
||||
color: @info-color;
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
&.success {
|
||||
background-color: @success-bg-color;
|
||||
color: @success-color;
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
&.warning {
|
||||
background-color: @warning-bg-color;
|
||||
color: @warning-color;
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
&.error {
|
||||
background-color: @error-bg-color;
|
||||
color: @error-color;
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.ant-alert-description {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
@ -24,13 +24,13 @@ import React, {
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
} from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import {
|
||||
msalLoginRequest,
|
||||
parseMSALResponse,
|
||||
} from '../../../utils/AuthProvider.util';
|
||||
import { getPopupSettingLink } from '../../../utils/BrowserUtils';
|
||||
import { Transi18next } from '../../../utils/CommonUtils';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
import Loader from '../../common/Loader/Loader';
|
||||
import {
|
||||
AuthenticatorRef,
|
||||
@ -96,7 +96,7 @@ const MsalAuthenticator = forwardRef<AuthenticatorRef, Props>(
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(e);
|
||||
if (e?.message?.includes('popup_window_error')) {
|
||||
showErrorToast(
|
||||
toast.error(
|
||||
<Transi18next
|
||||
i18nKey="message.popup-block-message"
|
||||
renderElement={
|
||||
|
||||
@ -37,7 +37,6 @@ import { getDomainPath } from '../../utils/RouterUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
import Loader from '../common/Loader/Loader';
|
||||
import ResizableLeftPanels from '../common/ResizablePanels/ResizableLeftPanels';
|
||||
import PageLayoutV1 from '../PageLayoutV1/PageLayoutV1';
|
||||
import './domain.less';
|
||||
import DomainDetailsPage from './DomainDetailsPage/DomainDetailsPage.component';
|
||||
import DomainsLeftPanel from './DomainLeftPanel/DomainLeftPanel.component';
|
||||
@ -177,6 +176,10 @@ const DomainPage = () => {
|
||||
}
|
||||
}, [rootDomains, domainFqn]);
|
||||
|
||||
if (domainLoading) {
|
||||
return <Loader />;
|
||||
}
|
||||
|
||||
if (!(viewBasicDomainPermission || viewAllDomainPermission)) {
|
||||
return (
|
||||
<ErrorPlaceHolder
|
||||
@ -186,23 +189,27 @@ const DomainPage = () => {
|
||||
);
|
||||
}
|
||||
|
||||
const pageContent = isEmpty(rootDomains) ? (
|
||||
<ErrorPlaceHolder
|
||||
buttonId="add-domain"
|
||||
className="mt-44"
|
||||
heading={t('label.domain')}
|
||||
permission={createDomainPermission}
|
||||
type={
|
||||
createDomainPermission
|
||||
? ERROR_PLACEHOLDER_TYPE.CREATE
|
||||
: ERROR_PLACEHOLDER_TYPE.CUSTOM
|
||||
}
|
||||
onClick={handleAddDomainClick}>
|
||||
{t('message.domains-not-configured')}
|
||||
</ErrorPlaceHolder>
|
||||
) : (
|
||||
if (isEmpty(rootDomains)) {
|
||||
return (
|
||||
<ErrorPlaceHolder
|
||||
buttonId="add-domain"
|
||||
className="mt-0-important"
|
||||
heading={t('label.domain')}
|
||||
permission={createDomainPermission}
|
||||
type={
|
||||
createDomainPermission
|
||||
? ERROR_PLACEHOLDER_TYPE.CREATE
|
||||
: ERROR_PLACEHOLDER_TYPE.CUSTOM
|
||||
}
|
||||
onClick={handleAddDomainClick}>
|
||||
{t('message.domains-not-configured')}
|
||||
</ErrorPlaceHolder>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ResizableLeftPanels
|
||||
className="content-height-with-resizable-panel domain-page"
|
||||
className="content-height-with-resizable-panel"
|
||||
firstPanel={{
|
||||
className: 'content-resizable-panel-container',
|
||||
minWidth: 280,
|
||||
@ -218,12 +225,6 @@ const DomainPage = () => {
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<PageLayoutV1 pageTitle={t('label.domain-plural')}>
|
||||
{domainLoading ? <Loader /> : pageContent}
|
||||
</PageLayoutV1>
|
||||
);
|
||||
};
|
||||
|
||||
export default DomainPage;
|
||||
|
||||
@ -15,9 +15,6 @@
|
||||
height: @domain-page-height;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.domain-page {
|
||||
margin-top: -12px;
|
||||
}
|
||||
|
||||
.domain-details-page-tabs {
|
||||
.ant-tabs-nav {
|
||||
|
||||
@ -21,8 +21,6 @@ import React, {
|
||||
ReactNode,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
import { useAlertStore } from '../../hooks/useAlertStore';
|
||||
import AlertBar from '../AlertBar/AlertBar';
|
||||
import DocumentTitle from '../common/DocumentTitle/DocumentTitle';
|
||||
import './../../styles/layout/page-layout.less';
|
||||
|
||||
@ -62,8 +60,6 @@ const PageLayoutV1: FC<PageLayoutProp> = ({
|
||||
mainContainerClassName = '',
|
||||
pageContainerStyle = {},
|
||||
}: PageLayoutProp) => {
|
||||
const { alert } = useAlertStore();
|
||||
|
||||
const contentWidth = useMemo(() => {
|
||||
if (leftPanel && rightPanel) {
|
||||
return `calc(100% - ${leftPanelWidth + rightPanelWidth}px)`;
|
||||
@ -103,35 +99,27 @@ const PageLayoutV1: FC<PageLayoutProp> = ({
|
||||
{leftPanel}
|
||||
</Col>
|
||||
)}
|
||||
<Col span={24}>
|
||||
<Col
|
||||
className={classNames(
|
||||
'page-layout-v1-center p-t-sm page-layout-v1-vertical-scroll',
|
||||
{
|
||||
'flex justify-center': center,
|
||||
},
|
||||
mainContainerClassName
|
||||
)}
|
||||
flex={contentWidth}
|
||||
offset={center ? 3 : 0}
|
||||
span={center ? 18 : 24}>
|
||||
<div className="alert-page-container">
|
||||
{alert && <AlertBar message={alert.message} type={alert.type} />}
|
||||
<div
|
||||
className={`page-content ${alert && 'page-content-shifted'}`}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
{rightPanel && (
|
||||
<Col
|
||||
className="page-layout-rightpanel page-layout-v1-vertical-scroll"
|
||||
flex={rightPanelWidth + 'px'}
|
||||
id="right-panelV1">
|
||||
{rightPanel}
|
||||
</Col>
|
||||
<Col
|
||||
className={classNames(
|
||||
'page-layout-v1-center p-t-sm page-layout-v1-vertical-scroll',
|
||||
{
|
||||
'flex justify-center': center,
|
||||
},
|
||||
mainContainerClassName
|
||||
)}
|
||||
flex={contentWidth}
|
||||
offset={center ? 3 : 0}
|
||||
span={center ? 18 : 24}>
|
||||
{children}
|
||||
</Col>
|
||||
{rightPanel && (
|
||||
<Col
|
||||
className="page-layout-rightpanel page-layout-v1-vertical-scroll"
|
||||
flex={rightPanelWidth + 'px'}
|
||||
id="right-panelV1">
|
||||
{rightPanel}
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { AlertProps } from 'antd';
|
||||
|
||||
/*
|
||||
* Copyright 2024 Collate.
|
||||
* Copyright 2022 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
|
||||
@ -12,7 +10,12 @@ import { AlertProps } from 'antd';
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export interface AlertBarProps {
|
||||
type: AlertProps['type'];
|
||||
message: string | JSX.Element;
|
||||
}
|
||||
|
||||
import { ToastOptions } from 'react-toastify';
|
||||
|
||||
export const TOAST_OPTIONS: ToastOptions = {
|
||||
autoClose: false,
|
||||
hideProgressBar: true,
|
||||
draggable: false,
|
||||
closeOnClick: false,
|
||||
};
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 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 { AlertProps } from 'antd';
|
||||
import { create } from 'zustand';
|
||||
|
||||
type AlertType = {
|
||||
type: AlertProps['type'];
|
||||
message: string | JSX.Element;
|
||||
};
|
||||
|
||||
interface AlertStore {
|
||||
alert: AlertType | undefined;
|
||||
animationClass: string;
|
||||
addAlert: (alert: AlertType, timer?: number) => void;
|
||||
resetAlert: () => void;
|
||||
}
|
||||
|
||||
export const useAlertStore = create<AlertStore>()((set) => ({
|
||||
alert: undefined,
|
||||
animationClass: '',
|
||||
addAlert: (alert: AlertType, timer?: number) => {
|
||||
set({ alert, animationClass: 'show-alert' });
|
||||
|
||||
const autoCloseTimer = timer ?? (alert.type === 'error' ? Infinity : 5000);
|
||||
|
||||
if (autoCloseTimer !== Infinity) {
|
||||
setTimeout(() => {
|
||||
set({ animationClass: 'hide-alert', alert: undefined });
|
||||
}, autoCloseTimer);
|
||||
}
|
||||
},
|
||||
resetAlert: () => {
|
||||
set({ alert: undefined });
|
||||
},
|
||||
}));
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "Aggregate",
|
||||
"airflow-config-plural": "Airflow-Konfigurationen",
|
||||
"alert": "Warnung",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "warnung",
|
||||
"alert-lowercase-plural": "warnungen",
|
||||
"alert-plural": "Warnungen",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "Aggregate",
|
||||
"airflow-config-plural": "airflow configs",
|
||||
"alert": "Alert",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "alert",
|
||||
"alert-lowercase-plural": "alerts",
|
||||
"alert-plural": "Alerts",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "Agregar",
|
||||
"airflow-config-plural": "Configuraciones de airflow",
|
||||
"alert": "Alerta",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "alerta",
|
||||
"alert-lowercase-plural": "alertas",
|
||||
"alert-plural": "Alertas",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "Aggregate",
|
||||
"airflow-config-plural": "Configurations Airflow",
|
||||
"alert": "Alerte",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "alerte",
|
||||
"alert-lowercase-plural": "alertes",
|
||||
"alert-plural": "Alertes",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "Agrupar",
|
||||
"airflow-config-plural": "configuracións de Airflow",
|
||||
"alert": "Alerta",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "alerta",
|
||||
"alert-lowercase-plural": "alertas",
|
||||
"alert-plural": "Alertas",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "כלול",
|
||||
"airflow-config-plural": "תצורות airflow",
|
||||
"alert": "התראה",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "התראה",
|
||||
"alert-lowercase-plural": "התראות",
|
||||
"alert-plural": "התראות",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "Aggregate",
|
||||
"airflow-config-plural": "Airflowの設定",
|
||||
"alert": "アラート",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "alert",
|
||||
"alert-lowercase-plural": "alerts",
|
||||
"alert-plural": "アラート",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "Agregaat",
|
||||
"airflow-config-plural": "Airflowconfiguraties",
|
||||
"alert": "Alert",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "alert",
|
||||
"alert-lowercase-plural": "alerts",
|
||||
"alert-plural": "Alerts",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "تجمیع",
|
||||
"airflow-config-plural": "پیکربندیهای ایرفلو",
|
||||
"alert": "هشدار",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "هشدار",
|
||||
"alert-lowercase-plural": "هشدارها",
|
||||
"alert-plural": "هشدارها",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "Agregado",
|
||||
"airflow-config-plural": "configs do airflow",
|
||||
"alert": "Alerta",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "alerta",
|
||||
"alert-lowercase-plural": "alertas",
|
||||
"alert-plural": "Alertas",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "Agregado",
|
||||
"airflow-config-plural": "configs do airflow",
|
||||
"alert": "Alerta",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "alerta",
|
||||
"alert-lowercase-plural": "alertas",
|
||||
"alert-plural": "Alertas",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "Aggregate",
|
||||
"airflow-config-plural": "конфиги airflow",
|
||||
"alert": "Предупреждение",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "предупреждение",
|
||||
"alert-lowercase-plural": "предупреждения",
|
||||
"alert-plural": "Предупреждения",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "รวม",
|
||||
"airflow-config-plural": "การกำหนดค่าของ airflow",
|
||||
"alert": "การแจ้งเตือน",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "การแจ้งเตือน",
|
||||
"alert-lowercase-plural": "การแจ้งเตือนหลายอย่าง",
|
||||
"alert-plural": "การแจ้งเตือนหลายอย่าง",
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"aggregate": "聚合",
|
||||
"airflow-config-plural": "Airflow 配置",
|
||||
"alert": "提醒",
|
||||
"alert-details": "Alert Details",
|
||||
"alert-lowercase": "提醒",
|
||||
"alert-lowercase-plural": "提醒",
|
||||
"alert-plural": "提醒",
|
||||
|
||||
@ -43,15 +43,6 @@ jest.mock('react-router-dom', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('../../components/PageLayoutV1/PageLayoutV1', () => {
|
||||
return jest.fn(({ children, pageTitle }) => (
|
||||
<div data-testid="page-layout-v1">
|
||||
<h1>{pageTitle}</h1>
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
));
|
||||
});
|
||||
|
||||
jest.mock('../../rest/observabilityAPI', () => ({
|
||||
getObservabilityAlertByFQN: jest
|
||||
.fn()
|
||||
|
||||
@ -30,7 +30,6 @@ import { OwnerLabel } from '../../components/common/OwnerLabel/OwnerLabel.compon
|
||||
import ResizablePanels from '../../components/common/ResizablePanels/ResizablePanels';
|
||||
import TitleBreadcrumb from '../../components/common/TitleBreadcrumb/TitleBreadcrumb.component';
|
||||
import EntityHeaderTitle from '../../components/Entity/EntityHeaderTitle/EntityHeaderTitle.component';
|
||||
import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1';
|
||||
import { ROUTES } from '../../constants/constants';
|
||||
import { GlobalSettingsMenuCategory } from '../../constants/GlobalSettings.constants';
|
||||
import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider';
|
||||
@ -328,140 +327,136 @@ function AlertDetailsPage({
|
||||
}
|
||||
|
||||
return (
|
||||
<PageLayoutV1 pageTitle={t('label.alert-details')}>
|
||||
<ResizablePanels
|
||||
hideSecondPanel
|
||||
className="content-height-with-resizable-panel"
|
||||
firstPanel={{
|
||||
className: 'content-resizable-panel-container',
|
||||
children: loadingCount ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<div
|
||||
className="steps-form-container"
|
||||
data-testid="alert-details-container">
|
||||
<Row
|
||||
className="add-notification-container p-x-lg p-t-md"
|
||||
gutter={[0, 16]}>
|
||||
<Col span={24}>
|
||||
<TitleBreadcrumb titleLinks={breadcrumb} />
|
||||
</Col>
|
||||
<ResizablePanels
|
||||
hideSecondPanel
|
||||
className="content-height-with-resizable-panel"
|
||||
firstPanel={{
|
||||
className: 'content-resizable-panel-container',
|
||||
children: loadingCount ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<div
|
||||
className="steps-form-container"
|
||||
data-testid="alert-details-container">
|
||||
<Row
|
||||
className="add-notification-container p-x-lg p-t-md"
|
||||
gutter={[0, 16]}>
|
||||
<Col span={24}>
|
||||
<TitleBreadcrumb titleLinks={breadcrumb} />
|
||||
</Col>
|
||||
|
||||
<Col span={24}>
|
||||
<Row justify="space-between">
|
||||
<Col span={21}>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<EntityHeaderTitle
|
||||
displayName={alertDetails?.displayName}
|
||||
icon={alertIcon}
|
||||
name={alertDetails?.name ?? ''}
|
||||
serviceName=""
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<div className="d-flex items-center flex-wrap gap-2">
|
||||
{ownerLoading ? (
|
||||
<Skeleton.Button
|
||||
active
|
||||
className="extra-info-skeleton"
|
||||
/>
|
||||
) : (
|
||||
<OwnerLabel
|
||||
hasPermission={editOwnersPermission}
|
||||
owners={alertDetails?.owners}
|
||||
onUpdate={onOwnerUpdate}
|
||||
/>
|
||||
)}
|
||||
{extraInfo}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col>
|
||||
<Space align="center" size={8}>
|
||||
{editPermission &&
|
||||
alertDetails?.provider !== ProviderType.System && (
|
||||
<Tooltip
|
||||
title={t('label.edit-entity', {
|
||||
entity: t('label.alert'),
|
||||
})}>
|
||||
<Button
|
||||
className="flex flex-center"
|
||||
data-testid="edit-button"
|
||||
icon={<EditIcon height={16} width={16} />}
|
||||
onClick={handleAlertEdit}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Col span={24}>
|
||||
<Row justify="space-between">
|
||||
<Col span={21}>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<EntityHeaderTitle
|
||||
displayName={alertDetails?.displayName}
|
||||
icon={alertIcon}
|
||||
name={alertDetails?.name ?? ''}
|
||||
serviceName=""
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<div className="d-flex items-center flex-wrap gap-2">
|
||||
{ownerLoading ? (
|
||||
<Skeleton.Button
|
||||
active
|
||||
className="extra-info-skeleton"
|
||||
/>
|
||||
) : (
|
||||
<OwnerLabel
|
||||
hasPermission={editOwnersPermission}
|
||||
owners={alertDetails?.owners}
|
||||
onUpdate={onOwnerUpdate}
|
||||
/>
|
||||
)}
|
||||
{deletePermission &&
|
||||
alertDetails?.provider !== ProviderType.System && (
|
||||
<Tooltip
|
||||
title={t('label.delete-entity', {
|
||||
entity: t('label.alert'),
|
||||
})}>
|
||||
<Button
|
||||
className="flex flex-center"
|
||||
data-testid="delete-button"
|
||||
icon={<DeleteIcon height={16} width={16} />}
|
||||
onClick={() => setShowDeleteModal(true)}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
{extraInfo}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col>
|
||||
<Space align="center" size={8}>
|
||||
{editPermission &&
|
||||
alertDetails?.provider !== ProviderType.System && (
|
||||
<Tooltip
|
||||
title={t('label.edit-entity', {
|
||||
entity: t('label.alert'),
|
||||
})}>
|
||||
<Button
|
||||
className="flex flex-center"
|
||||
data-testid="edit-button"
|
||||
icon={<EditIcon height={16} width={16} />}
|
||||
onClick={handleAlertEdit}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
{deletePermission &&
|
||||
alertDetails?.provider !== ProviderType.System && (
|
||||
<Tooltip
|
||||
title={t('label.delete-entity', {
|
||||
entity: t('label.alert'),
|
||||
})}>
|
||||
<Button
|
||||
className="flex flex-center"
|
||||
data-testid="delete-button"
|
||||
icon={<DeleteIcon height={16} width={16} />}
|
||||
onClick={() => setShowDeleteModal(true)}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
|
||||
<Col
|
||||
className="alert-description"
|
||||
data-testid="alert-description"
|
||||
span={24}>
|
||||
<DescriptionV1
|
||||
description={alertDetails?.description}
|
||||
entityType={EntityType.EVENT_SUBSCRIPTION}
|
||||
hasEditAccess={editDescriptionPermission}
|
||||
isEdit={showDescriptionModal}
|
||||
showCommentsIcon={false}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
/>
|
||||
</Col>
|
||||
<Col
|
||||
className="alert-description"
|
||||
data-testid="alert-description"
|
||||
span={24}>
|
||||
<DescriptionV1
|
||||
description={alertDetails?.description}
|
||||
entityType={EntityType.EVENT_SUBSCRIPTION}
|
||||
hasEditAccess={editDescriptionPermission}
|
||||
isEdit={showDescriptionModal}
|
||||
showCommentsIcon={false}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={24}>
|
||||
<Tabs
|
||||
activeKey={tab}
|
||||
className="m-b-lg"
|
||||
items={tabItems}
|
||||
onTabClick={handleTabChange}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<DeleteWidgetModal
|
||||
afterDeleteAction={handleAlertDelete}
|
||||
allowSoftDelete={false}
|
||||
entityId={alertDetails?.id ?? ''}
|
||||
entityName={getEntityName(alertDetails)}
|
||||
entityType={EntityType.SUBSCRIPTION}
|
||||
visible={showDeleteModal}
|
||||
onCancel={hideDeleteModal}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
minWidth: 700,
|
||||
flex: 0.7,
|
||||
}}
|
||||
pageTitle={t('label.entity-detail-plural', {
|
||||
entity: t('label.alert'),
|
||||
})}
|
||||
secondPanel={{
|
||||
children: <></>,
|
||||
minWidth: 0,
|
||||
className: 'content-resizable-panel-container',
|
||||
}}
|
||||
/>
|
||||
</PageLayoutV1>
|
||||
<Col span={24}>
|
||||
<Tabs
|
||||
activeKey={tab}
|
||||
className="m-b-lg"
|
||||
items={tabItems}
|
||||
onTabClick={handleTabChange}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<DeleteWidgetModal
|
||||
afterDeleteAction={handleAlertDelete}
|
||||
allowSoftDelete={false}
|
||||
entityId={alertDetails?.id ?? ''}
|
||||
entityName={getEntityName(alertDetails)}
|
||||
entityType={EntityType.SUBSCRIPTION}
|
||||
visible={showDeleteModal}
|
||||
onCancel={hideDeleteModal}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
minWidth: 700,
|
||||
flex: 0.7,
|
||||
}}
|
||||
pageTitle={t('label.entity-detail-plural', { entity: t('label.alert') })}
|
||||
secondPanel={{
|
||||
children: <></>,
|
||||
minWidth: 0,
|
||||
className: 'content-resizable-panel-container',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -63,10 +63,6 @@ jest.mock('../../components/common/ResizablePanels/ResizableLeftPanels', () => {
|
||||
));
|
||||
});
|
||||
|
||||
jest.mock('../../components/PageLayoutV1/PageLayoutV1', () => {
|
||||
return jest.fn().mockImplementation(({ children }) => <div>{children}</div>);
|
||||
});
|
||||
|
||||
jest.mock('react-router-dom', () => {
|
||||
return {
|
||||
...jest.requireActual('react-router-dom'),
|
||||
|
||||
@ -24,7 +24,6 @@ import {
|
||||
import LeftPanelCard from '../../components/common/LeftPanelCard/LeftPanelCard';
|
||||
import ResizableLeftPanels from '../../components/common/ResizablePanels/ResizableLeftPanels';
|
||||
import TabsLabel from '../../components/common/TabsLabel/TabsLabel.component';
|
||||
import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1';
|
||||
import { ROUTES } from '../../constants/constants';
|
||||
import { getDataQualityPagePath } from '../../utils/RouterUtils';
|
||||
import './data-quality-page.less';
|
||||
@ -69,78 +68,76 @@ const DataQualityPage = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<PageLayoutV1 pageTitle={t('label.data-quality')}>
|
||||
<ResizableLeftPanels
|
||||
className="content-height-with-resizable-panel"
|
||||
firstPanel={{
|
||||
className: 'content-resizable-panel-container',
|
||||
minWidth: 280,
|
||||
flex: 0.13,
|
||||
children: (
|
||||
<LeftPanelCard id="data-quality">
|
||||
<Menu
|
||||
className="custom-menu custom-menu-with-description data-quality-page-left-panel-menu"
|
||||
data-testid="tabs"
|
||||
items={menuItems}
|
||||
mode="inline"
|
||||
selectedKeys={[
|
||||
activeTab ?? DataQualityClassBase.getDefaultActiveTab(),
|
||||
]}
|
||||
onClick={handleTabChange}
|
||||
/>
|
||||
</LeftPanelCard>
|
||||
),
|
||||
}}
|
||||
pageTitle="Quality"
|
||||
secondPanel={{
|
||||
children: (
|
||||
<DataQualityProvider>
|
||||
<Row
|
||||
className="page-container"
|
||||
data-testid="data-insight-container"
|
||||
gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<Typography.Title
|
||||
className="m-b-md p-x-md"
|
||||
data-testid="page-title"
|
||||
level={5}>
|
||||
{t('label.data-quality')}
|
||||
</Typography.Title>
|
||||
<Typography.Paragraph
|
||||
className="text-grey-muted p-x-md"
|
||||
data-testid="page-sub-title">
|
||||
{t('message.page-sub-header-for-data-quality')}
|
||||
</Typography.Paragraph>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Switch>
|
||||
{tabDetailsComponent.map((tab) => (
|
||||
<Route
|
||||
exact
|
||||
component={tab.component}
|
||||
key={tab.key}
|
||||
path={tab.path}
|
||||
/>
|
||||
))}
|
||||
<ResizableLeftPanels
|
||||
className="content-height-with-resizable-panel"
|
||||
firstPanel={{
|
||||
className: 'content-resizable-panel-container',
|
||||
minWidth: 280,
|
||||
flex: 0.13,
|
||||
children: (
|
||||
<LeftPanelCard id="data-quality">
|
||||
<Menu
|
||||
className="custom-menu custom-menu-with-description data-quality-page-left-panel-menu"
|
||||
data-testid="tabs"
|
||||
items={menuItems}
|
||||
mode="inline"
|
||||
selectedKeys={[
|
||||
activeTab ?? DataQualityClassBase.getDefaultActiveTab(),
|
||||
]}
|
||||
onClick={handleTabChange}
|
||||
/>
|
||||
</LeftPanelCard>
|
||||
),
|
||||
}}
|
||||
pageTitle="Quality"
|
||||
secondPanel={{
|
||||
children: (
|
||||
<DataQualityProvider>
|
||||
<Row
|
||||
className="page-container"
|
||||
data-testid="data-insight-container"
|
||||
gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<Typography.Title
|
||||
className="m-b-md p-x-md"
|
||||
data-testid="page-title"
|
||||
level={5}>
|
||||
{t('label.data-quality')}
|
||||
</Typography.Title>
|
||||
<Typography.Paragraph
|
||||
className="text-grey-muted p-x-md"
|
||||
data-testid="page-sub-title">
|
||||
{t('message.page-sub-header-for-data-quality')}
|
||||
</Typography.Paragraph>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Switch>
|
||||
{tabDetailsComponent.map((tab) => (
|
||||
<Route
|
||||
exact
|
||||
component={tab.component}
|
||||
key={tab.key}
|
||||
path={tab.path}
|
||||
/>
|
||||
))}
|
||||
|
||||
<Route exact path={ROUTES.DATA_QUALITY}>
|
||||
<Redirect
|
||||
to={getDataQualityPagePath(
|
||||
DataQualityClassBase.getDefaultActiveTab()
|
||||
)}
|
||||
/>
|
||||
</Route>
|
||||
</Switch>
|
||||
</Col>
|
||||
</Row>
|
||||
</DataQualityProvider>
|
||||
),
|
||||
className: 'content-resizable-panel-container p-t-sm',
|
||||
minWidth: 800,
|
||||
flex: 0.87,
|
||||
}}
|
||||
/>
|
||||
</PageLayoutV1>
|
||||
<Route exact path={ROUTES.DATA_QUALITY}>
|
||||
<Redirect
|
||||
to={getDataQualityPagePath(
|
||||
DataQualityClassBase.getDefaultActiveTab()
|
||||
)}
|
||||
/>
|
||||
</Route>
|
||||
</Switch>
|
||||
</Col>
|
||||
</Row>
|
||||
</DataQualityProvider>
|
||||
),
|
||||
className: 'content-resizable-panel-container p-t-sm',
|
||||
minWidth: 800,
|
||||
flex: 0.87,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -29,7 +29,6 @@ import {
|
||||
ModifiedGlossary,
|
||||
useGlossaryStore,
|
||||
} from '../../../components/Glossary/useGlossary.store';
|
||||
import PageLayoutV1 from '../../../components/PageLayoutV1/PageLayoutV1';
|
||||
import { FQN_SEPARATOR_CHAR } from '../../../constants/char.constants';
|
||||
import { PAGE_SIZE_LARGE, ROUTES } from '../../../constants/constants';
|
||||
import { GLOSSARIES_DOCS } from '../../../constants/docs.constants';
|
||||
@ -349,6 +348,24 @@ const GlossaryPage = () => {
|
||||
return <ErrorPlaceHolder type={ERROR_PLACEHOLDER_TYPE.PERMISSION} />;
|
||||
}
|
||||
|
||||
if (glossaries.length === 0 && !isLoading) {
|
||||
return (
|
||||
<ErrorPlaceHolder
|
||||
buttonId="add-glossary"
|
||||
className="mt-0-important"
|
||||
doc={GLOSSARIES_DOCS}
|
||||
heading={t('label.glossary')}
|
||||
permission={createGlossaryPermission}
|
||||
type={
|
||||
createGlossaryPermission
|
||||
? ERROR_PLACEHOLDER_TYPE.CREATE
|
||||
: ERROR_PLACEHOLDER_TYPE.NO_DATA
|
||||
}
|
||||
onClick={handleAddGlossaryClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const glossaryElement = (
|
||||
<div className="p-t-sm">
|
||||
{isRightPanelLoading ? (
|
||||
@ -416,27 +433,7 @@ const GlossaryPage = () => {
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<PageLayoutV1 pageTitle={t('label.glossary-plural')}>
|
||||
{glossaries.length === 0 && !isLoading ? (
|
||||
<ErrorPlaceHolder
|
||||
buttonId="add-glossary"
|
||||
className="mt-44"
|
||||
doc={GLOSSARIES_DOCS}
|
||||
heading={t('label.glossary')}
|
||||
permission={createGlossaryPermission}
|
||||
type={
|
||||
createGlossaryPermission
|
||||
? ERROR_PLACEHOLDER_TYPE.CREATE
|
||||
: ERROR_PLACEHOLDER_TYPE.NO_DATA
|
||||
}
|
||||
onClick={handleAddGlossaryClick}
|
||||
/>
|
||||
) : (
|
||||
resizableLayout
|
||||
)}
|
||||
</PageLayoutV1>
|
||||
);
|
||||
return <>{resizableLayout}</>;
|
||||
};
|
||||
|
||||
export default GlossaryPage;
|
||||
|
||||
@ -46,15 +46,6 @@ jest.mock('../../../context/PermissionProvider/PermissionProvider', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../../../components/PageLayoutV1/PageLayoutV1', () => {
|
||||
return jest.fn(({ children, pageTitle }) => (
|
||||
<div data-testid="page-layout-v1">
|
||||
<h1>{pageTitle}</h1>
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
));
|
||||
});
|
||||
|
||||
jest.mock('../../../components/Glossary/GlossaryV1.component', () => {
|
||||
return jest.fn().mockImplementation((props) => (
|
||||
<div>
|
||||
|
||||
@ -26,7 +26,6 @@ import ResizablePanels from '../../components/common/ResizablePanels/ResizablePa
|
||||
import ServiceDocPanel from '../../components/common/ServiceDocPanel/ServiceDocPanel';
|
||||
import TitleBreadcrumb from '../../components/common/TitleBreadcrumb/TitleBreadcrumb.component';
|
||||
import { TitleBreadcrumbProps } from '../../components/common/TitleBreadcrumb/TitleBreadcrumb.interface';
|
||||
import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1';
|
||||
import { GlobalSettingsMenuCategory } from '../../constants/GlobalSettings.constants';
|
||||
import { OPEN_METADATA } from '../../constants/service-guide.constant';
|
||||
import {
|
||||
@ -117,130 +116,128 @@ const LineageConfigPage = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<PageLayoutV1 pageTitle={t('label.lineage-config')}>
|
||||
<ResizablePanels
|
||||
className="content-height-with-resizable-panel"
|
||||
firstPanel={{
|
||||
className: 'content-resizable-panel-container',
|
||||
children: (
|
||||
<div
|
||||
className="max-width-md w-9/10 service-form-container"
|
||||
data-testid="add-metric-container">
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<TitleBreadcrumb titleLinks={breadcrumbs} />
|
||||
</Col>
|
||||
<ResizablePanels
|
||||
className="content-height-with-resizable-panel"
|
||||
firstPanel={{
|
||||
className: 'content-resizable-panel-container',
|
||||
children: (
|
||||
<div
|
||||
className="max-width-md w-9/10 service-form-container"
|
||||
data-testid="add-metric-container">
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<TitleBreadcrumb titleLinks={breadcrumbs} />
|
||||
</Col>
|
||||
|
||||
<Col span={24}>
|
||||
<Typography.Title
|
||||
className="m-b-0"
|
||||
data-testid="heading"
|
||||
level={5}>
|
||||
{t('label.lineage')}
|
||||
</Typography.Title>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form
|
||||
form={form}
|
||||
id="lineage-config"
|
||||
initialValues={lineageConfig}
|
||||
layout="vertical"
|
||||
onFinish={handleSave}
|
||||
onFocus={handleFieldFocus}>
|
||||
<Form.Item
|
||||
id="root/upstreamDepth"
|
||||
label={t('label.upstream-depth')}
|
||||
name="upstreamDepth"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t('message.upstream-depth-message'),
|
||||
},
|
||||
]}>
|
||||
<Input
|
||||
data-testid="field-upstream"
|
||||
max={5}
|
||||
min={1}
|
||||
type="number"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Col span={24}>
|
||||
<Typography.Title
|
||||
className="m-b-0"
|
||||
data-testid="heading"
|
||||
level={5}>
|
||||
{t('label.lineage')}
|
||||
</Typography.Title>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form
|
||||
form={form}
|
||||
id="lineage-config"
|
||||
initialValues={lineageConfig}
|
||||
layout="vertical"
|
||||
onFinish={handleSave}
|
||||
onFocus={handleFieldFocus}>
|
||||
<Form.Item
|
||||
id="root/upstreamDepth"
|
||||
label={t('label.upstream-depth')}
|
||||
name="upstreamDepth"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t('message.upstream-depth-message'),
|
||||
},
|
||||
]}>
|
||||
<Input
|
||||
data-testid="field-upstream"
|
||||
max={5}
|
||||
min={1}
|
||||
type="number"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
className="m-t-sm"
|
||||
id="root/downstreamDepth"
|
||||
label={t('label.downstream-depth')}
|
||||
name="downstreamDepth"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t('message.downstream-depth-message'),
|
||||
},
|
||||
]}>
|
||||
<Input
|
||||
data-testid="field-downstream"
|
||||
max={5}
|
||||
min={1}
|
||||
type="number"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
className="m-t-sm"
|
||||
id="root/downstreamDepth"
|
||||
label={t('label.downstream-depth')}
|
||||
name="downstreamDepth"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t('message.downstream-depth-message'),
|
||||
},
|
||||
]}>
|
||||
<Input
|
||||
data-testid="field-downstream"
|
||||
max={5}
|
||||
min={1}
|
||||
type="number"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
className="m-t-sm"
|
||||
id="root/lineageLayer"
|
||||
label={t('label.lineage-layer')}
|
||||
name="lineageLayer">
|
||||
<Select data-testid="field-lineage-layer">
|
||||
<Select.Option value={LineageLayer.EntityLineage}>
|
||||
{t('label.entity-lineage')}
|
||||
</Select.Option>
|
||||
<Select.Option value={LineageLayer.ColumnLevelLineage}>
|
||||
{t('label.column-level-lineage')}
|
||||
</Select.Option>
|
||||
<Select.Option value={LineageLayer.DataObservability}>
|
||||
{t('label.data-observability')}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Row className="m-b-xl" justify="end">
|
||||
<Col className="d-flex justify-end gap-2" span={24}>
|
||||
<Button
|
||||
data-testid="cancel-button"
|
||||
onClick={() => history.goBack()}>
|
||||
{t('label.cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="save-button"
|
||||
form="lineage-config"
|
||||
htmlType="submit"
|
||||
loading={isUpdating}
|
||||
type="primary">
|
||||
{t('label.save')}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
),
|
||||
minWidth: 700,
|
||||
flex: 0.7,
|
||||
}}
|
||||
pageTitle={t('label.lineage-config')}
|
||||
secondPanel={{
|
||||
className: 'service-doc-panel content-resizable-panel-container',
|
||||
minWidth: 400,
|
||||
flex: 0.3,
|
||||
children: (
|
||||
<ServiceDocPanel
|
||||
activeField={activeField}
|
||||
serviceName="LineageConfiguration"
|
||||
serviceType={OPEN_METADATA}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</PageLayoutV1>
|
||||
<Form.Item
|
||||
className="m-t-sm"
|
||||
id="root/lineageLayer"
|
||||
label={t('label.lineage-layer')}
|
||||
name="lineageLayer">
|
||||
<Select data-testid="field-lineage-layer">
|
||||
<Select.Option value={LineageLayer.EntityLineage}>
|
||||
{t('label.entity-lineage')}
|
||||
</Select.Option>
|
||||
<Select.Option value={LineageLayer.ColumnLevelLineage}>
|
||||
{t('label.column-level-lineage')}
|
||||
</Select.Option>
|
||||
<Select.Option value={LineageLayer.DataObservability}>
|
||||
{t('label.data-observability')}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Row className="m-b-xl" justify="end">
|
||||
<Col className="d-flex justify-end gap-2" span={24}>
|
||||
<Button
|
||||
data-testid="cancel-button"
|
||||
onClick={() => history.goBack()}>
|
||||
{t('label.cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="save-button"
|
||||
form="lineage-config"
|
||||
htmlType="submit"
|
||||
loading={isUpdating}
|
||||
type="primary">
|
||||
{t('label.save')}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
),
|
||||
minWidth: 700,
|
||||
flex: 0.7,
|
||||
}}
|
||||
pageTitle={t('label.lineage-config')}
|
||||
secondPanel={{
|
||||
className: 'service-doc-panel content-resizable-panel-container',
|
||||
minWidth: 400,
|
||||
flex: 0.3,
|
||||
children: (
|
||||
<ServiceDocPanel
|
||||
activeField={activeField}
|
||||
serviceName="LineageConfiguration"
|
||||
serviceType={OPEN_METADATA}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -120,73 +120,75 @@ export const PersonaPage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
if (isEmpty(persona) && !isLoading) {
|
||||
return (
|
||||
<>
|
||||
{errorPlaceHolder}
|
||||
{Boolean(addEditPersona) && (
|
||||
<AddEditPersonaForm
|
||||
persona={addEditPersona}
|
||||
onCancel={handlePersonalAddEditCancel}
|
||||
onSave={handlePersonaAddEditSave}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<PageLayoutV1 pageTitle={t('label.persona-plural')}>
|
||||
{isEmpty(persona) && !isLoading ? (
|
||||
<div className="mt-44">
|
||||
{errorPlaceHolder}
|
||||
{Boolean(addEditPersona) && (
|
||||
<AddEditPersonaForm
|
||||
persona={addEditPersona}
|
||||
onCancel={handlePersonalAddEditCancel}
|
||||
onSave={handlePersonaAddEditSave}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Row className="user-listing page-container p-b-md" gutter={[16, 16]}>
|
||||
<Row className="user-listing page-container p-b-md" gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<TitleBreadcrumb titleLinks={breadcrumbs} />
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<PageHeader data={PAGE_HEADERS.PERSONAS} />
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Space align="center" className="w-full justify-end" size={16}>
|
||||
<Button
|
||||
data-testid="add-persona-button"
|
||||
type="primary"
|
||||
onClick={handleAddNewPersona}>
|
||||
{t('label.add-entity', { entity: t('label.persona') })}
|
||||
</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
|
||||
{isLoading
|
||||
? [1, 2, 3].map((key) => (
|
||||
<Col key={key} span={8}>
|
||||
<Card>
|
||||
<Skeleton active paragraph title />
|
||||
</Card>
|
||||
</Col>
|
||||
))
|
||||
: persona?.map((persona) => (
|
||||
<Col key={persona.id} span={8}>
|
||||
<PersonaDetailsCard persona={persona} />
|
||||
</Col>
|
||||
))}
|
||||
|
||||
{showPagination && (
|
||||
<Col span={24}>
|
||||
<TitleBreadcrumb titleLinks={breadcrumbs} />
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<PageHeader data={PAGE_HEADERS.PERSONAS} />
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Space align="center" className="w-full justify-end" size={16}>
|
||||
<Button
|
||||
data-testid="add-persona-button"
|
||||
type="primary"
|
||||
onClick={handleAddNewPersona}>
|
||||
{t('label.add-entity', { entity: t('label.persona') })}
|
||||
</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
|
||||
{isLoading
|
||||
? [1, 2, 3].map((key) => (
|
||||
<Col key={key} span={8}>
|
||||
<Card>
|
||||
<Skeleton active paragraph title />
|
||||
</Card>
|
||||
</Col>
|
||||
))
|
||||
: persona?.map((persona) => (
|
||||
<Col key={persona.id} span={8}>
|
||||
<PersonaDetailsCard persona={persona} />
|
||||
</Col>
|
||||
))}
|
||||
|
||||
{showPagination && (
|
||||
<Col span={24}>
|
||||
<NextPrevious
|
||||
currentPage={currentPage}
|
||||
isLoading={isLoading}
|
||||
pageSize={pageSize}
|
||||
paging={paging}
|
||||
pagingHandler={handlePersonaPageChange}
|
||||
onShowSizeChange={handlePageSizeChange}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
{Boolean(addEditPersona) && (
|
||||
<AddEditPersonaForm
|
||||
persona={addEditPersona}
|
||||
onCancel={handlePersonalAddEditCancel}
|
||||
onSave={handlePersonaAddEditSave}
|
||||
<NextPrevious
|
||||
currentPage={currentPage}
|
||||
isLoading={isLoading}
|
||||
pageSize={pageSize}
|
||||
paging={paging}
|
||||
pagingHandler={handlePersonaPageChange}
|
||||
onShowSizeChange={handlePageSizeChange}
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
)}
|
||||
</Col>
|
||||
)}
|
||||
{Boolean(addEditPersona) && (
|
||||
<AddEditPersonaForm
|
||||
persona={addEditPersona}
|
||||
onCancel={handlePersonalAddEditCancel}
|
||||
onSave={handlePersonaAddEditSave}
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
</PageLayoutV1>
|
||||
);
|
||||
};
|
||||
|
||||
@ -20,20 +20,6 @@
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.alert-page-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.page-content {
|
||||
position: relative;
|
||||
top: 0;
|
||||
transition: top 1s ease-in-out;
|
||||
}
|
||||
|
||||
.page-content-shifted {
|
||||
top: 64px;
|
||||
}
|
||||
|
||||
.page-layout-v1-left-panel {
|
||||
border: @global-border;
|
||||
border-radius: @border-radius-base;
|
||||
|
||||
@ -110,10 +110,6 @@
|
||||
@team-avatar-bg: #0950c51a;
|
||||
@om-navbar-height: ~'var(--ant-navbar-height)';
|
||||
@sidebar-width: 60px;
|
||||
@error-bg-color: rgb(from @error-color r g b / 0.1);
|
||||
@success-bg-color: rgb(from @success-color r g b / 0.1);
|
||||
@warning-bg-color: rgb(from @warning-color r g b / 0.1);
|
||||
@info-bg-color: rgb(from @info-color r g b / 0.1);
|
||||
|
||||
// Sizing
|
||||
@page-height: calc(100vh - @om-navbar-height);
|
||||
|
||||
@ -11,53 +11,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { AlertProps } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { isEmpty, isString } from 'lodash';
|
||||
import React from 'react';
|
||||
import { ReactComponent as ErrorIcon } from '../assets/svg/ic-error.svg';
|
||||
import { ReactComponent as InfoIcon } from '../assets/svg/ic-info-tag.svg';
|
||||
import { ReactComponent as SuccessIcon } from '../assets/svg/ic-success.svg';
|
||||
import { ReactComponent as WarningIcon } from '../assets/svg/ic-warning-tag.svg';
|
||||
import { toast } from 'react-toastify';
|
||||
import { ClientErrors } from '../enums/Axios.enum';
|
||||
import { useAlertStore } from '../hooks/useAlertStore';
|
||||
import i18n from './i18next/LocalUtil';
|
||||
import { getErrorText } from './StringsUtils';
|
||||
|
||||
export const getIconAndClassName = (type: AlertProps['type']) => {
|
||||
switch (type) {
|
||||
case 'info':
|
||||
return {
|
||||
icon: InfoIcon,
|
||||
className: 'info',
|
||||
};
|
||||
|
||||
case 'success':
|
||||
return {
|
||||
icon: SuccessIcon,
|
||||
className: 'success',
|
||||
};
|
||||
|
||||
case 'warning':
|
||||
return {
|
||||
icon: WarningIcon,
|
||||
className: 'warning',
|
||||
};
|
||||
|
||||
case 'error':
|
||||
return {
|
||||
icon: ErrorIcon,
|
||||
className: 'error',
|
||||
};
|
||||
|
||||
default:
|
||||
return {
|
||||
icon: null,
|
||||
className: '',
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const hashCode = (str: string) => {
|
||||
let hash = 0,
|
||||
i,
|
||||
@ -81,18 +42,15 @@ export const hashCode = (str: string) => {
|
||||
* @param autoCloseTimer Set the delay in ms to close the toast automatically.
|
||||
*/
|
||||
export const showErrorToast = (
|
||||
error: AxiosError | string | JSX.Element,
|
||||
error: AxiosError | string,
|
||||
fallbackText?: string,
|
||||
autoCloseTimer?: number,
|
||||
callback?: (value: React.SetStateAction<string | JSX.Element>) => void
|
||||
callback?: (value: React.SetStateAction<string>) => void
|
||||
) => {
|
||||
let errorMessage: string | JSX.Element;
|
||||
|
||||
if (React.isValidElement(error)) {
|
||||
errorMessage = error;
|
||||
} else if (isString(error)) {
|
||||
let errorMessage;
|
||||
if (isString(error)) {
|
||||
errorMessage = error.toString();
|
||||
} else if ('config' in error && 'response' in error) {
|
||||
} else {
|
||||
const method = error.config?.method?.toUpperCase();
|
||||
const fallback =
|
||||
fallbackText && fallbackText.length > 0
|
||||
@ -111,15 +69,12 @@ export const showErrorToast = (
|
||||
) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
errorMessage = fallbackText ?? i18n.t('server.unexpected-error');
|
||||
}
|
||||
|
||||
callback && callback(errorMessage);
|
||||
|
||||
useAlertStore
|
||||
.getState()
|
||||
.addAlert({ type: 'error', message: errorMessage }, autoCloseTimer);
|
||||
toast.error(errorMessage, {
|
||||
toastId: hashCode(errorMessage),
|
||||
autoClose: autoCloseTimer,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -128,9 +83,9 @@ export const showErrorToast = (
|
||||
* @param autoCloseTimer Set the delay in ms to close the toast automatically. `Default: 5000`
|
||||
*/
|
||||
export const showSuccessToast = (message: string, autoCloseTimer = 5000) => {
|
||||
useAlertStore
|
||||
.getState()
|
||||
.addAlert({ type: 'success', message }, autoCloseTimer);
|
||||
toast.success(message, {
|
||||
autoClose: autoCloseTimer,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -139,5 +94,15 @@ export const showSuccessToast = (message: string, autoCloseTimer = 5000) => {
|
||||
* @param autoCloseTimer Set the delay in ms to close the toast automatically. `Default: 5000`
|
||||
*/
|
||||
export const showInfoToast = (message: string, autoCloseTimer = 5000) => {
|
||||
useAlertStore.getState().addAlert({ type: 'info', message }, autoCloseTimer);
|
||||
toast.info(message, {
|
||||
autoClose: autoCloseTimer,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear all the toast messages.
|
||||
*/
|
||||
export const clearAllToasts = () => {
|
||||
toast.clearWaitingQueue();
|
||||
toast.dismiss();
|
||||
};
|
||||
|
||||
@ -12481,6 +12481,13 @@ react-test-renderer@^16.14.0:
|
||||
react-is "^16.8.6"
|
||||
scheduler "^0.19.1"
|
||||
|
||||
react-toastify@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-8.2.0.tgz#ef7d56bdfdc6272ca6b228368ab564721c3a3244"
|
||||
integrity sha512-Pg2Ju7NngAamarFvLwqrFomJ57u/Ay6i6zfLurt/qPynWkAkOthu6vxfqYpJCyNhHRhR4hu7+bySSeWWJu6PAg==
|
||||
dependencies:
|
||||
clsx "^1.1.1"
|
||||
|
||||
react-transition-group@2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user