From da5034b5206ca3f68c9286fdb20c5732485bb99f Mon Sep 17 00:00:00 2001 From: darth-coder00 <86726556+darth-coder00@users.noreply.github.com> Date: Thu, 31 Mar 2022 02:30:19 +0530 Subject: [PATCH] Fix deleted users from teams and create new user issue (#3759) --- .../ui/mock-api/v1/search/query/GET.js | 2 + .../ui/mock-api/v1/search/query/GET.json | 359 ++++++++++++++++++ .../src/main/resources/ui/src/AppState.ts | 3 + .../ui/src/components/UserList/UserList.tsx | 3 +- .../CreateUserPage.component.tsx | 1 + .../CreateUserPage/CreateUserPage.test.tsx | 35 +- .../main/resources/ui/src/utils/TeamUtils.ts | 24 ++ 7 files changed, 424 insertions(+), 3 deletions(-) create mode 100644 openmetadata-ui/src/main/resources/ui/mock-api/v1/search/query/GET.json create mode 100644 openmetadata-ui/src/main/resources/ui/src/utils/TeamUtils.ts diff --git a/openmetadata-ui/src/main/resources/ui/mock-api/v1/search/query/GET.js b/openmetadata-ui/src/main/resources/ui/mock-api/v1/search/query/GET.js index 1d1b2f71a89..9e09f8445be 100644 --- a/openmetadata-ui/src/main/resources/ui/mock-api/v1/search/query/GET.js +++ b/openmetadata-ui/src/main/resources/ui/mock-api/v1/search/query/GET.js @@ -25,6 +25,8 @@ module.exports = function (request, response) { if (q.toString().includes('owner')) { targetFileName = 'GET_owner.json'; } + } else { + targetFileName = 'GET.json'; } const filePath = path.join(__dirname, targetFileName); // If file does not exist then respond with 404 header diff --git a/openmetadata-ui/src/main/resources/ui/mock-api/v1/search/query/GET.json b/openmetadata-ui/src/main/resources/ui/mock-api/v1/search/query/GET.json new file mode 100644 index 00000000000..477e11cd095 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/mock-api/v1/search/query/GET.json @@ -0,0 +1,359 @@ +{ + "took": 8, + "timed_out": false, + "_shards": { + "total": 4, + "successful": 4, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": { + "value": 2, + "relation": "eq" + }, + "max_score": 2.4637282, + "hits": [ + { + "_index": "table_search_index", + "_type": "_doc", + "_id": "07244140-402d-48e0-9b68-3a0f078d334b", + "_score": 2.4637282, + "_source": { + "name": "raw_product_catalog", + "fqdn": "bigquery_gcp.shopify.raw_product_catalog", + "service": "bigquery_gcp", + "deleted": false, + "suggest": [ + { + "input": "bigquery_gcp.shopify.raw_product_catalog", + "weight": 5 + }, + { + "input": "raw_product_catalog", + "weight": 10 + } + ], + "description": "This is a raw product catalog table contains the product listing, price, seller etc.. represented in our online DB.", + "tags": [ + "Health care.Term 2", + "PII.Sensitive", + "PersonalData.Personal", + "User.Address" + ], + "followers": [], + "database": "shopify", + "display_name": "raw_product_catalog", + "service_type": "BigQuery", + "service_category": "databaseService", + "entity_type": "table", + "last_updated_timestamp": 1646948504918, + "change_descriptions": [ + { + "updatedBy": "anonymous", + "updatedAt": 1646772061575, + "fieldsAdded": [], + "fieldsUpdated": [], + "fieldsDeleted": [] + }, + { + "updatedBy": "anonymous", + "fieldsAdded": [ + { + "newValue": "[{\"tagFQN\":\"Health care.Term 2\",\"source\":\"Glossary\",\"labelType\":\"Manual\",\"state\":\"Confirmed\"}]", + "name": "columns.platform.tags" + } + ], + "fieldsUpdated": [], + "fieldsDeleted": [], + "updatedAt": 1646897095509 + }, + { + "updatedBy": "anonymous", + "fieldsAdded": [ + { + "newValue": "[{\"tagFQN\":\"PII.Sensitive\",\"description\":\"PII which if lost, compromised, or disclosed without authorization, could result in substantial harm, embarrassment, inconvenience, or unfairness to an individual.\",\"source\":\"Tag\",\"labelType\":\"Derived\",\"state\":\"Confirmed\"},{\"tagFQN\":\"PersonalData.Personal\",\"description\":\"Data that can be used to directly or indirectly identify a person.\",\"source\":\"Tag\",\"labelType\":\"Derived\",\"state\":\"Confirmed\"},{\"tagFQN\":\"User.Address\",\"source\":\"Tag\",\"labelType\":\"Manual\",\"state\":\"Confirmed\"}]", + "name": "columns.store_address.tags" + } + ], + "fieldsUpdated": [], + "fieldsDeleted": [], + "updatedAt": 1646897119471 + }, + { + "updatedBy": "anonymous", + "fieldsAdded": [ + { + "newValue": "[{\"tagFQN\":\"Health care.term1.COBRA\",\"source\":\"Glossary\",\"labelType\":\"Manual\",\"state\":\"Confirmed\"}]", + "name": "columns.comments.tags" + } + ], + "fieldsUpdated": [], + "fieldsDeleted": [], + "updatedAt": 1646898527281 + }, + { + "updatedBy": "anonymous", + "fieldsAdded": [ + { + "newValue": "{\"id\":\"ea4851dc-76d5-4d00-bd87-39bee118f297\",\"type\":\"user\",\"name\":\"aaron_johnson0\",\"displayName\":\"Aaron Johnson\"}", + "name": "owner" + } + ], + "fieldsUpdated": [], + "fieldsDeleted": [], + "updatedAt": 1646948483587 + }, + { + "updatedBy": "anonymous", + "fieldsAdded": [], + "fieldsUpdated": [], + "fieldsDeleted": [ + { + "name": "columns.comments.tags", + "oldValue": "[{\"tagFQN\":\"Health care.term1.COBRA\",\"source\":\"Glossary\",\"labelType\":\"Manual\",\"state\":\"Confirmed\"}]" + } + ], + "updatedAt": 1646948504918 + } + ], + "table_id": "07244140-402d-48e0-9b68-3a0f078d334b", + "table_type": "Regular", + "column_names": [ + "comments", + "products", + "platform", + "store_address", + "first_order_date", + "last_order_date" + ], + "column_descriptions": [ + null, + null, + null, + null, + "The date (ISO 8601) and time (UTC) when the customer placed their first order. The format is YYYY-MM-DD HH:mm:ss (for example, 2016-02-05 17:04:01).", + "The date (ISO 8601) and time (UTC) when the customer placed their most recent order. The format is YYYY-MM-DD HH:mm:ss (for example, 2016-02-05 17:04:01)." + ], + "owner": "ea4851dc-76d5-4d00-bd87-39bee118f297", + "weekly_stats": "7000", + "weekly_percentile_rank": "10", + "daily_stats": "1000", + "daily_percentile_rank": "7" + } + }, + { + "_index": "table_search_index", + "_type": "_doc", + "_id": "07244140-402d-48e0-9b68-3a0f078d334b", + "_score": 2.4637282, + "_source": { + "name": "raw_customer", + "fqdn": "bigquery_gcp.shopify.raw_customer", + "service": "bigquery_gcp", + "deleted": false, + "suggest": [ + { + "input": "bigquery_gcp.shopify.raw_customer", + "weight": 5 + }, + { + "input": "raw_customer", + "weight": 10 + } + ], + "description": "This is a raw product catalog table contains the product listing, price, seller etc.. represented in our online DB.", + "tags": [ + "Health care.Term 2", + "PII.Sensitive", + "PersonalData.Personal", + "User.Address" + ], + "followers": [], + "database": "shopify", + "display_name": "raw_customer", + "service_type": "BigQuery", + "service_category": "databaseService", + "entity_type": "table", + "last_updated_timestamp": 1646948504918, + "change_descriptions": [ + { + "updatedBy": "anonymous", + "updatedAt": 1646772061575, + "fieldsAdded": [], + "fieldsUpdated": [], + "fieldsDeleted": [] + }, + { + "updatedBy": "anonymous", + "fieldsAdded": [ + { + "newValue": "[{\"tagFQN\":\"Health care.Term 2\",\"source\":\"Glossary\",\"labelType\":\"Manual\",\"state\":\"Confirmed\"}]", + "name": "columns.platform.tags" + } + ], + "fieldsUpdated": [], + "fieldsDeleted": [], + "updatedAt": 1646897095509 + }, + { + "updatedBy": "anonymous", + "fieldsAdded": [ + { + "newValue": "[{\"tagFQN\":\"PII.Sensitive\",\"description\":\"PII which if lost, compromised, or disclosed without authorization, could result in substantial harm, embarrassment, inconvenience, or unfairness to an individual.\",\"source\":\"Tag\",\"labelType\":\"Derived\",\"state\":\"Confirmed\"},{\"tagFQN\":\"PersonalData.Personal\",\"description\":\"Data that can be used to directly or indirectly identify a person.\",\"source\":\"Tag\",\"labelType\":\"Derived\",\"state\":\"Confirmed\"},{\"tagFQN\":\"User.Address\",\"source\":\"Tag\",\"labelType\":\"Manual\",\"state\":\"Confirmed\"}]", + "name": "columns.store_address.tags" + } + ], + "fieldsUpdated": [], + "fieldsDeleted": [], + "updatedAt": 1646897119471 + }, + { + "updatedBy": "anonymous", + "fieldsAdded": [ + { + "newValue": "[{\"tagFQN\":\"Health care.term1.COBRA\",\"source\":\"Glossary\",\"labelType\":\"Manual\",\"state\":\"Confirmed\"}]", + "name": "columns.comments.tags" + } + ], + "fieldsUpdated": [], + "fieldsDeleted": [], + "updatedAt": 1646898527281 + }, + { + "updatedBy": "anonymous", + "fieldsAdded": [ + { + "newValue": "{\"id\":\"ea4851dc-76d5-4d00-bd87-39bee118f297\",\"type\":\"user\",\"name\":\"aaron_johnson0\",\"displayName\":\"Aaron Johnson\"}", + "name": "owner" + } + ], + "fieldsUpdated": [], + "fieldsDeleted": [], + "updatedAt": 1646948483587 + }, + { + "updatedBy": "anonymous", + "fieldsAdded": [], + "fieldsUpdated": [], + "fieldsDeleted": [ + { + "name": "columns.comments.tags", + "oldValue": "[{\"tagFQN\":\"Health care.term1.COBRA\",\"source\":\"Glossary\",\"labelType\":\"Manual\",\"state\":\"Confirmed\"}]" + } + ], + "updatedAt": 1646948504918 + } + ], + "table_id": "07244140-402d-48e0-9b68-3a0f078d334b", + "table_type": "Regular", + "column_names": [ + "comments", + "products", + "platform", + "store_address", + "first_order_date", + "last_order_date" + ], + "column_descriptions": [ + null, + null, + null, + null, + "The date (ISO 8601) and time (UTC) when the customer placed their first order. The format is YYYY-MM-DD HH:mm:ss (for example, 2016-02-05 17:04:01).", + "The date (ISO 8601) and time (UTC) when the customer placed their most recent order. The format is YYYY-MM-DD HH:mm:ss (for example, 2016-02-05 17:04:01)." + ], + "owner": "ea4851dc-76d5-4d00-bd87-39bee118f297" + } + } + ] + }, + "aggregations": { + "sterms#EntityType": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "dashboard", + "doc_count": 1 + }, + { + "key": "table", + "doc_count": 1 + } + ] + }, + "sterms#ServiceCategory": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "dashboardService", + "doc_count": 1 + }, + { + "key": "databaseService", + "doc_count": 1 + } + ] + }, + "sterms#Tier": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [] + }, + "sterms#Service": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "BigQuery", + "doc_count": 1 + }, + { + "key": "Superset", + "doc_count": 1 + } + ] + }, + "sterms#Tags": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "Health care.Term 2", + "doc_count": 1 + }, + { + "key": "Health care.term 3.Term 4", + "doc_count": 1 + }, + { + "key": "PII.None", + "doc_count": 1 + }, + { + "key": "PII.Sensitive", + "doc_count": 1 + }, + { + "key": "PersonalData.Personal", + "doc_count": 1 + }, + { + "key": "PersonalData.SpecialCategory", + "doc_count": 1 + }, + { + "key": "User.Address", + "doc_count": 1 + }, + { + "key": "User.Biometric", + "doc_count": 1 + } + ] + } + } + } + \ No newline at end of file diff --git a/openmetadata-ui/src/main/resources/ui/src/AppState.ts b/openmetadata-ui/src/main/resources/ui/src/AppState.ts index 2618e5e432e..96c07aee687 100644 --- a/openmetadata-ui/src/main/resources/ui/src/AppState.ts +++ b/openmetadata-ui/src/main/resources/ui/src/AppState.ts @@ -55,6 +55,9 @@ class AppState { }); } + addUser(data: User) { + this.users = [...this.users, data]; + } updateUsers(data: Array) { this.users = data; } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/UserList/UserList.tsx b/openmetadata-ui/src/main/resources/ui/src/components/UserList/UserList.tsx index 0ee22fd4e48..d9dd30fb169 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/UserList/UserList.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/UserList/UserList.tsx @@ -23,6 +23,7 @@ import { Role } from '../../generated/entity/teams/role'; import { Team } from '../../generated/entity/teams/team'; import { User } from '../../generated/entity/teams/user'; import { getCountBadge } from '../../utils/CommonUtils'; +import { getActiveUsers } from '../../utils/TeamUtils'; import { Button } from '../buttons/Button/Button'; import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder'; import NonAdminAction from '../common/non-admin-action/NonAdminAction'; @@ -308,7 +309,7 @@ const UserList: FunctionComponent = ({

{getCountBadge( - team.users?.length || 0, + getActiveUsers(team.users).length, '', isTeamBadgeActive(team.name) )} diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.component.tsx index faecc46f687..7b292a2f891 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.component.tsx @@ -78,6 +78,7 @@ const CreateUserPage = () => { createUser(userData) .then((res) => { if (res.data) { + AppState.addUser(res.data); setStatus('success'); setTimeout(() => { setStatus('initial'); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.test.tsx index b898128dc00..de9e938aedd 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.test.tsx @@ -11,9 +11,16 @@ * limitations under the License. */ -import { findByTestId, findByText, render } from '@testing-library/react'; +import { + act, + findByTestId, + findByText, + fireEvent, + render, +} from '@testing-library/react'; import React, { ReactNode } from 'react'; import { MemoryRouter } from 'react-router-dom'; +import { createUser } from '../../axiosAPIs/userAPI'; import AddUserPageComponent from './CreateUserPage.component'; jest.mock('../../components/containers/PageContainerV1', () => { @@ -33,9 +40,17 @@ jest.mock('../../hooks/authHooks', () => ({ })); jest.mock('../../components/CreateUser/CreateUser.component', () => { - return jest.fn().mockReturnValue(
CreateUser component
); + return jest + .fn() + .mockImplementation(({ onSave }) => ( +
CreateUser component
+ )); }); +jest.mock('../../axiosAPIs/userAPI', () => ({ + createUser: jest.fn().mockImplementation(() => Promise.resolve()), +})); + jest.mock('../../AppState', () => jest.fn().mockReturnValue({ userRoles: [], @@ -43,6 +58,8 @@ jest.mock('../../AppState', () => }) ); +const mockCreateUser = jest.fn(() => Promise.resolve({})); + describe('Test AddUserPage component', () => { it('AddUserPage component should render properly', async () => { const { container } = render(, { @@ -58,4 +75,18 @@ describe('Test AddUserPage component', () => { expect(pageContainerV1).toBeInTheDocument(); expect(createUserComponent).toBeInTheDocument(); }); + + it('should create user', async () => { + (createUser as jest.Mock).mockImplementationOnce(mockCreateUser); + + const { container } = render(, { + wrapper: MemoryRouter, + }); + + await act(async () => { + fireEvent.click(await findByText(container, /CreateUser component/i)); + }); + + expect(mockCreateUser).toBeCalled(); + }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TeamUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/TeamUtils.ts new file mode 100644 index 00000000000..486fe284eb5 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TeamUtils.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2021 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 { isNil } from 'lodash'; +import { EntityReference } from '../generated/entity/teams/team'; + +/** + * To get filtered list of non-deleted(active) users + * @param users List of users + * @returns List of non-deleted(active) users + */ +export const getActiveUsers = (users?: Array) => { + return !isNil(users) ? users.filter((item) => !item.deleted) : []; +};