UI: Fix miscellaneous UI issues (#4451)

This commit is contained in:
Vivek Ratnavel Subramanian 2022-04-24 17:53:46 -07:00 committed by GitHub
parent e880224da8
commit e82cd76e1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 100 additions and 31 deletions

View File

@ -227,7 +227,8 @@ public class ChangeEventHandler implements EventHandler {
// In this case, the entity itself got deleted // In this case, the entity itself got deleted
// for which there will be no change description. // for which there will be no change description.
String message = String message =
String.format("Deleted %s **%s**", entityInterface.getEntityType(), entityInterface.getFullyQualifiedName()); String.format(
"Deleted **%s**: `%s`", entityInterface.getEntityType(), entityInterface.getFullyQualifiedName());
EntityLink about = EntityLink about =
new EntityLink(entityInterface.getEntityType(), entityInterface.getFullyQualifiedName(), null, null, null); new EntityLink(entityInterface.getEntityType(), entityInterface.getFullyQualifiedName(), null, null, null);
Thread thread = Thread thread =

View File

@ -214,7 +214,7 @@ public final class ChangeEventParser {
case ADD: case ADD:
String fieldValue = getFieldValue(newFieldValue); String fieldValue = getFieldValue(newFieldValue);
if (Entity.FIELD_FOLLOWERS.equals(updatedField)) { if (Entity.FIELD_FOLLOWERS.equals(updatedField)) {
message = String.format("Started to follow %s `%s`", link.getEntityType(), link.getEntityFQN()); message = String.format("Started to follow **%s** `%s`", link.getEntityType(), link.getEntityFQN());
} else if (fieldValue != null && !fieldValue.isEmpty()) { } else if (fieldValue != null && !fieldValue.isEmpty()) {
message = String.format("Added **%s**: `%s`", updatedField, fieldValue); message = String.format("Added **%s**: `%s`", updatedField, fieldValue);
} }
@ -238,7 +238,7 @@ public final class ChangeEventParser {
private static String getPlainTextUpdateMessage(String updatedField, String oldValue, String newValue) { private static String getPlainTextUpdateMessage(String updatedField, String oldValue, String newValue) {
// Get diff of old value and new value // Get diff of old value and new value
String diff = getPlaintextDiff(oldValue, newValue); String diff = getPlaintextDiff(oldValue, newValue);
return nullOrEmpty(diff) ? StringUtils.EMPTY : String.format("Updated **%s** : %s", updatedField, diff); return nullOrEmpty(diff) ? StringUtils.EMPTY : String.format("Updated **%s**: %s", updatedField, diff);
} }
private static String getObjectUpdateMessage(String updatedField, JsonObject oldJson, JsonObject newJson) { private static String getObjectUpdateMessage(String updatedField, JsonObject oldJson, JsonObject newJson) {
@ -256,7 +256,7 @@ public final class ChangeEventParser {
if (newJson.containsKey("name")) { if (newJson.containsKey("name")) {
updatedField = String.format("%s.%s", updatedField, newJson.getString("name")); updatedField = String.format("%s.%s", updatedField, newJson.getString("name"));
} }
return String.format("Updated **%s** : <br/> %s", updatedField, updates); return String.format("Updated **%s**: <br/> %s", updatedField, updates);
} }
private static String getUpdateMessage(String updatedField, Object oldValue, Object newValue) { private static String getUpdateMessage(String updatedField, Object oldValue, Object newValue) {

View File

@ -550,7 +550,7 @@ public class FeedResourceTest extends CatalogApplicationTest {
assertEquals(initialThreadCount + 3, threads.getPaging().getTotal()); assertEquals(initialThreadCount + 3, threads.getPaging().getTotal());
assertEquals(initialThreadCount + 3, threads.getData().size()); assertEquals(initialThreadCount + 3, threads.getData().size());
assertEquals( assertEquals(
String.format("Started to follow table `%s`", TABLE2.getFullyQualifiedName()), String.format("Started to follow **table** `%s`", TABLE2.getFullyQualifiedName()),
threads.getData().get(0).getMessage()); threads.getData().get(0).getMessage());
assertEquals("Message 2", threads.getData().get(1).getMessage()); assertEquals("Message 2", threads.getData().get(1).getMessage());

View File

@ -113,7 +113,7 @@ public class ChangeEventParserTest extends CatalogApplicationTest {
assertEquals(1, messages.size()); assertEquals(1, messages.size());
assertEquals( assertEquals(
"Updated **description** : <span class=\"diff-removed\">old</span>" "Updated **description**: <span class=\"diff-removed\">old</span>"
+ "<span class=\"diff-added\">new</span> description", + "<span class=\"diff-added\">new</span> description",
messages.values().iterator().next()); messages.values().iterator().next());
@ -161,7 +161,7 @@ public class ChangeEventParserTest extends CatalogApplicationTest {
assertEquals(1, messages.size()); assertEquals(1, messages.size());
assertEquals( assertEquals(
"Updated **columns.lo_orderpriority** : <br/> name: <span class=\"diff-removed\">\"lo_order\"</span><span class=\"diff-added\">\"lo_orderpriority\"</span> <br/> displayName: <span class=\"diff-removed\">\"lo_order\"</span><span class=\"diff-added\">\"lo_orderpriority\"</span> <br/> fullyQualifiedName: \"local_mysql.sample_db.lineorder.<span class=\"diff-removed\">lo_order\"</span><span class=\"diff-added\">lo_orderpriority\"</span>", "Updated **columns.lo_orderpriority**: <br/> name: <span class=\"diff-removed\">\"lo_order\"</span><span class=\"diff-added\">\"lo_orderpriority\"</span> <br/> displayName: <span class=\"diff-removed\">\"lo_order\"</span><span class=\"diff-added\">\"lo_orderpriority\"</span> <br/> fullyQualifiedName: \"local_mysql.sample_db.lineorder.<span class=\"diff-removed\">lo_order\"</span><span class=\"diff-added\">lo_orderpriority\"</span>",
messages.values().iterator().next()); messages.values().iterator().next());
// Simulate a change of datatype change in column // Simulate a change of datatype change in column
@ -179,7 +179,7 @@ public class ChangeEventParserTest extends CatalogApplicationTest {
assertEquals(1, messages.size()); assertEquals(1, messages.size());
assertEquals( assertEquals(
"Updated **columns.lo_orderpriority** : <br/> dataType: <span class=\"diff-removed\">\"BLOB\"</span><span class=\"diff-added\">\"INT\"</span> <br/> dataTypeDisplay: <span class=\"diff-removed\">\"blob\"</span><span class=\"diff-added\">\"int\"</span>", "Updated **columns.lo_orderpriority**: <br/> dataType: <span class=\"diff-removed\">\"BLOB\"</span><span class=\"diff-added\">\"INT\"</span> <br/> dataTypeDisplay: <span class=\"diff-removed\">\"blob\"</span><span class=\"diff-added\">\"int\"</span>",
messages.values().iterator().next()); messages.values().iterator().next());
// Simulate multiple changes to columns // Simulate multiple changes to columns
@ -197,7 +197,7 @@ public class ChangeEventParserTest extends CatalogApplicationTest {
assertEquals(1, messages.size()); assertEquals(1, messages.size());
assertEquals( assertEquals(
"Updated **columns** : lo_orderpriority<span class=\"diff-added\">, newColumn</span>", "Updated **columns**: lo_orderpriority<span class=\"diff-added\">, newColumn</span>",
messages.values().iterator().next()); messages.values().iterator().next());
} }
} }

View File

@ -63,8 +63,8 @@ const FeedCardHeader: FC<FeedHeaderProp> = ({
}; };
const getUserData = () => { const getUserData = () => {
const displayName = userData.displayName ?? '';
const name = userData.name ?? ''; const name = userData.name ?? '';
const displayName = userData.displayName ?? name;
const teams = getNonDeletedTeams(userData.teams ?? []); const teams = getNonDeletedTeams(userData.teams ?? []);
const roles = userData.roles; const roles = userData.roles;
const isAdmin = userData?.isAdmin; const isAdmin = userData?.isAdmin;
@ -89,7 +89,9 @@ const FeedCardHeader: FC<FeedHeaderProp> = ({
{displayName} {displayName}
</span> </span>
</a> </a>
<span className="tw-text-grey-muted">{name}</span> {displayName !== name ? (
<span className="tw-text-grey-muted">{name}</span>
) : null}
</div> </div>
</div> </div>
<div className="tw-text-left"> <div className="tw-text-left">

View File

@ -693,7 +693,7 @@ const ColumnTestForm = ({
theme="primary" theme="primary"
variant="text" variant="text"
onClick={onFormCancel}> onClick={onFormCancel}>
Discard Cancel
</Button> </Button>
<Button <Button
className="tw-w-16 tw-h-10" className="tw-w-16 tw-h-10"

View File

@ -358,7 +358,7 @@ const TableTestForm = ({
theme="primary" theme="primary"
variant="text" variant="text"
onClick={onFormCancel}> onClick={onFormCancel}>
Discard Cancel
</Button> </Button>
<Button <Button
className="tw-w-16 tw-h-10" className="tw-w-16 tw-h-10"

View File

@ -265,7 +265,7 @@ const AddGlossary = ({
theme="primary" theme="primary"
variant="text" variant="text"
onClick={onCancel}> onClick={onCancel}>
Discard Cancel
</Button> </Button>
{getSaveButton()} {getSaveButton()}
</div> </div>

View File

@ -487,7 +487,7 @@ const AddGlossaryTerm = ({
theme="primary" theme="primary"
variant="text" variant="text"
onClick={onCancel}> onClick={onCancel}>
Discard Cancel
</Button> </Button>
{getSaveButton()} {getSaveButton()}
</Field> </Field>

View File

@ -101,7 +101,7 @@ const SelectServiceType = ({
theme="primary" theme="primary"
variant="text" variant="text"
onClick={onCancel}> onClick={onCancel}>
<span>Discard</span> <span>Cancel</span>
</Button> </Button>
<Button <Button

View File

@ -821,7 +821,7 @@ const AddWebhook: FunctionComponent<AddWebhookProps> = ({
theme="primary" theme="primary"
variant="text" variant="text"
onClick={onCancel}> onClick={onCancel}>
Discard Cancel
</Button> </Button>
{getSaveButton()} {getSaveButton()}
</div> </div>
@ -830,7 +830,7 @@ const AddWebhook: FunctionComponent<AddWebhookProps> = ({
{data && isDelete && ( {data && isDelete && (
<ConfirmationModal <ConfirmationModal
bodyText={`You want to delete webhook ${data.name} permanently? This action cannot be reverted.`} bodyText={`You want to delete webhook ${data.name} permanently? This action cannot be reverted.`}
cancelText="Discard" cancelText="Cancel"
confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error" confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error"
confirmText="Delete" confirmText="Delete"
header="Are you sure?" header="Are you sure?"

View File

@ -338,7 +338,7 @@ const CreateUser = ({
theme="primary" theme="primary"
variant="text" variant="text"
onClick={onCancel}> onClick={onCancel}>
Discard Cancel
</Button> </Button>
{getSaveButton()} {getSaveButton()}
</Field> </Field>

View File

@ -219,7 +219,7 @@ const DataQualityTable = ({
deleteSelection.data?.testCase?.columnTestType || deleteSelection.data?.testCase?.columnTestType ||
deleteSelection.data?.testCase?.tableTestType deleteSelection.data?.testCase?.tableTestType
} permanently? This action cannot be reverted.`} } permanently? This action cannot be reverted.`}
cancelText="Discard" cancelText="Cancel"
confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error" confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error"
confirmText={ confirmText={
deleteSelection.state === 'waiting' ? ( deleteSelection.state === 'waiting' ? (

View File

@ -302,7 +302,7 @@ const GlossaryV1 = ({
{selectedData && isDelete && ( {selectedData && isDelete && (
<ConfirmationModal <ConfirmationModal
bodyText={`You want to delete ${selectedData.name} permanently? This action cannot be reverted.`} bodyText={`You want to delete ${selectedData.name} permanently? This action cannot be reverted.`}
cancelText="Discard" cancelText="Cancel"
confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error" confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error"
confirmText="Delete" confirmText="Delete"
header="Are you sure?" header="Are you sure?"

View File

@ -103,7 +103,7 @@ const EntityDeleteModal: FC<Prop> = ({
theme="primary" theme="primary"
variant="text" variant="text"
onClick={onCancel}> onClick={onCancel}>
Discard Cancel
</Button> </Button>
{loadingState === 'waiting' ? ( {loadingState === 'waiting' ? (
<Button <Button

View File

@ -52,7 +52,7 @@ interface Props {
const ConnectionConfigForm: FunctionComponent<Props> = ({ const ConnectionConfigForm: FunctionComponent<Props> = ({
data, data,
okText = 'Save', okText = 'Save',
cancelText = 'Discard', cancelText = 'Cancel',
serviceCategory, serviceCategory,
status, status,
onCancel, onCancel,

View File

@ -0,0 +1,16 @@
/*
* 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.
*/
.table-title:hover {
border-bottom: solid 1px;
}

View File

@ -11,7 +11,10 @@
* limitations under the License. * limitations under the License.
*/ */
import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; import {
faAngleRight,
faExclamationCircle,
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { isString, isUndefined, startCase, uniqueId } from 'lodash'; import { isString, isUndefined, startCase, uniqueId } from 'lodash';
import { ExtraInfo } from 'Models'; import { ExtraInfo } from 'Models';
@ -26,6 +29,7 @@ import { TableType } from '../../../generated/entity/data/table';
import { TagLabel } from '../../../generated/type/tagLabel'; import { TagLabel } from '../../../generated/type/tagLabel';
import { serviceTypeLogo } from '../../../utils/ServiceUtils'; import { serviceTypeLogo } from '../../../utils/ServiceUtils';
import { getEntityLink, getUsagePercentile } from '../../../utils/TableUtils'; import { getEntityLink, getUsagePercentile } from '../../../utils/TableUtils';
import './TableDataCard.style.css';
import TableDataCardBody from './TableDataCardBody'; import TableDataCardBody from './TableDataCardBody';
type Props = { type Props = {
@ -112,6 +116,26 @@ const TableDataCard: FunctionComponent<Props> = ({
} }
}; };
const fqnParts = fullyQualifiedName.split(FQN_SEPARATOR_CHAR);
const separatorHtml = (
<span className="tw-px-2">
<FontAwesomeIcon
className="tw-text-xs tw-cursor-default tw-text-gray-400 tw-align-middle"
icon={faAngleRight}
/>
</span>
);
const tableTitle = fqnParts.map((part, i) => {
const separator = i !== fqnParts.length - 1 ? separatorHtml : null;
return (
<span key={i}>
<span>{part}</span>
{separator}
</span>
);
});
return ( return (
<div <div
className="tw-bg-white tw-p-3 tw-border tw-border-main tw-rounded-md" className="tw-bg-white tw-p-3 tw-border tw-border-main tw-rounded-md"
@ -130,7 +154,7 @@ const TableDataCard: FunctionComponent<Props> = ({
data-testid="table-link" data-testid="table-link"
id={`${id}Title`} id={`${id}Title`}
onClick={handleLinkClick}> onClick={handleLinkClick}>
{fullyQualifiedName} <span className="table-title">{tableTitle}</span>
</button> </button>
</h6> </h6>
{deleted && ( {deleted && (

View File

@ -352,6 +352,18 @@ export const getGlossaryPath = (fqn?: string) => {
return path; return path;
}; };
export const getParentGlossaryPath = (fqn?: string) => {
if (fqn) {
const parts = fqn.split(FQN_SEPARATOR_CHAR);
if (parts.length > 1) {
// remove the last part to get parent FQN
fqn = parts.slice(0, -1).join(FQN_SEPARATOR_CHAR);
}
}
return getGlossaryPath(fqn);
};
export const getGlossaryTermsPath = ( export const getGlossaryTermsPath = (
glossaryName: string, glossaryName: string,
glossaryTerm = '' glossaryTerm = ''

View File

@ -24,7 +24,10 @@ import {
import AddGlossaryTerm from '../../components/AddGlossaryTerm/AddGlossaryTerm.component'; import AddGlossaryTerm from '../../components/AddGlossaryTerm/AddGlossaryTerm.component';
import PageContainerV1 from '../../components/containers/PageContainerV1'; import PageContainerV1 from '../../components/containers/PageContainerV1';
import Loader from '../../components/Loader/Loader'; import Loader from '../../components/Loader/Loader';
import { getGlossaryPath } from '../../constants/constants'; import {
getGlossaryPath,
getParentGlossaryPath,
} from '../../constants/constants';
import { CreateGlossaryTerm } from '../../generated/api/data/createGlossaryTerm'; import { CreateGlossaryTerm } from '../../generated/api/data/createGlossaryTerm';
import { Glossary } from '../../generated/entity/data/glossary'; import { Glossary } from '../../generated/entity/data/glossary';
import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm'; import { GlossaryTerm } from '../../generated/entity/data/glossaryTerm';
@ -44,8 +47,12 @@ const AddGlossaryTermPage = () => {
const [parentGlossaryData, setParentGlossaryData] = useState<GlossaryTerm>(); const [parentGlossaryData, setParentGlossaryData] = useState<GlossaryTerm>();
const goToGlossaryPath = (path: string) => {
history.push(path);
};
const goToGlossary = (name = '') => { const goToGlossary = (name = '') => {
history.push(getGlossaryPath(name)); goToGlossaryPath(getGlossaryPath(name));
}; };
const handleCancel = () => { const handleCancel = () => {
@ -68,7 +75,9 @@ const AddGlossaryTermPage = () => {
setStatus('success'); setStatus('success');
setTimeout(() => { setTimeout(() => {
setStatus('initial'); setStatus('initial');
goToGlossary(res?.data?.fullyQualifiedName); goToGlossaryPath(
getParentGlossaryPath(res?.data?.fullyQualifiedName)
);
}, 500); }, 500);
} else { } else {
handleSaveFailure( handleSaveFailure(

View File

@ -558,7 +558,7 @@ const ServicesPage = () => {
return isConfirmationModalOpen ? ( return isConfirmationModalOpen ? (
<ConfirmationModal <ConfirmationModal
bodyText={`You want to delete service ${deleteSelection.name} permanently? This action cannot be reverted.`} bodyText={`You want to delete service ${deleteSelection.name} permanently? This action cannot be reverted.`}
cancelText="Discard" cancelText="Cancel"
confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error" confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error"
confirmText="Delete" confirmText="Delete"
header="Are you sure?" header="Are you sure?"

View File

@ -92,7 +92,7 @@ describe('Test AddUsersModal component', () => {
onSave={mockSave} onSave={mockSave}
/> />
); );
const discard = await findByText(container, /Discard/i); const discard = await findByText(container, /Cancel/i);
fireEvent.click(discard); fireEvent.click(discard);
expect(mockCancel).toBeCalledTimes(1); expect(mockCancel).toBeCalledTimes(1);

View File

@ -123,7 +123,7 @@ const AddUsersModal = ({
theme="primary" theme="primary"
variant="text" variant="text"
onClick={onCancel}> onClick={onCancel}>
Discard Cancel
</Button> </Button>
<Button <Button
data-testid="AddUserSave" data-testid="AddUserSave"

View File

@ -474,4 +474,9 @@
@apply tw-border-gray-300 tw-border tw-text-error focus:tw-outline-none focus:tw-bg-transparent hover:tw-border-error focus:tw-border-error @apply tw-border-gray-300 tw-border tw-text-error focus:tw-outline-none focus:tw-bg-transparent hover:tw-border-error focus:tw-border-error
hover:tw-text-error focus:tw-text-error focus:tw-ring focus:tw-ring-error; hover:tw-text-error focus:tw-text-error focus:tw-ring focus:tw-ring-error;
} }
/* ToastUI Editor style */
.ProseMirror .placeholder {
@apply tw-text-grey-muted;
}
} }