mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-19 14:37:52 +00:00
parent
171477cbb9
commit
d18198bb20
@ -19,11 +19,15 @@ import {
|
|||||||
FormatedUsersData,
|
FormatedUsersData,
|
||||||
} from 'Models';
|
} from 'Models';
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { UrlEntityCharRegEx } from '../../constants/regex.constants';
|
|
||||||
import { PageLayoutType } from '../../enums/layout.enum';
|
import { PageLayoutType } from '../../enums/layout.enum';
|
||||||
import { CreateGlossaryTerm } from '../../generated/api/data/createGlossaryTerm';
|
import { CreateGlossaryTerm } from '../../generated/api/data/createGlossaryTerm';
|
||||||
import { TermReference } from '../../generated/entity/data/glossaryTerm';
|
import { TermReference } from '../../generated/entity/data/glossaryTerm';
|
||||||
import { errorMsg, requiredField } from '../../utils/CommonUtils';
|
import {
|
||||||
|
errorMsg,
|
||||||
|
isUrlFriendlyName,
|
||||||
|
isValidUrl,
|
||||||
|
requiredField,
|
||||||
|
} from '../../utils/CommonUtils';
|
||||||
import SVGIcons from '../../utils/SvgUtils';
|
import SVGIcons from '../../utils/SvgUtils';
|
||||||
import { Button } from '../buttons/Button/Button';
|
import { Button } from '../buttons/Button/Button';
|
||||||
import MarkdownWithPreview from '../common/editor/MarkdownWithPreview';
|
import MarkdownWithPreview from '../common/editor/MarkdownWithPreview';
|
||||||
@ -57,6 +61,7 @@ const AddGlossaryTerm = ({
|
|||||||
const [showErrorMsg, setShowErrorMsg] = useState<{ [key: string]: boolean }>({
|
const [showErrorMsg, setShowErrorMsg] = useState<{ [key: string]: boolean }>({
|
||||||
name: false,
|
name: false,
|
||||||
invalidName: false,
|
invalidName: false,
|
||||||
|
invalidReferences: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [name, setName] = useState('');
|
const [name, setName] = useState('');
|
||||||
@ -158,12 +163,29 @@ const AddGlossaryTerm = ({
|
|||||||
const newFormValues = [...references];
|
const newFormValues = [...references];
|
||||||
newFormValues[i][field] = value;
|
newFormValues[i][field] = value;
|
||||||
setReferences(newFormValues);
|
setReferences(newFormValues);
|
||||||
|
setShowErrorMsg((prev) => {
|
||||||
|
return { ...prev, invalidReferences: false };
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateForm = () => {
|
const isValidReferences = (refs: TermReference[]): boolean => {
|
||||||
|
let retVal = true;
|
||||||
|
for (const ref of refs) {
|
||||||
|
if (!isValidUrl(ref.endpoint || '')) {
|
||||||
|
retVal = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
};
|
||||||
|
|
||||||
|
const validateForm = (refs: TermReference[]) => {
|
||||||
const errMsg = {
|
const errMsg = {
|
||||||
name: !name.trim(),
|
name: !name.trim(),
|
||||||
invalidName: UrlEntityCharRegEx.test(name.trim()),
|
invalidName: !isUrlFriendlyName(name.trim()),
|
||||||
|
invalidReferences: !isValidReferences(refs),
|
||||||
};
|
};
|
||||||
setShowErrorMsg(errMsg);
|
setShowErrorMsg(errMsg);
|
||||||
|
|
||||||
@ -171,16 +193,19 @@ const AddGlossaryTerm = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
const updatedReference = references.filter(
|
const updatedReference = references
|
||||||
(ref) => !isEmpty(ref.endpoint) && !isEmpty(ref.name)
|
.map((ref) => ({
|
||||||
);
|
name: ref.name?.trim(),
|
||||||
|
endpoint: ref.endpoint?.trim(),
|
||||||
|
}))
|
||||||
|
.filter((ref) => !isEmpty(ref.endpoint) && !isEmpty(ref.name));
|
||||||
|
|
||||||
const updatedTerms = relatedTerms.map((term) => ({
|
const updatedTerms = relatedTerms.map((term) => ({
|
||||||
id: term.id,
|
id: term.id,
|
||||||
type: term.type,
|
type: term.type,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (validateForm()) {
|
if (validateForm(updatedReference)) {
|
||||||
const data: CreateGlossaryTerm = {
|
const data: CreateGlossaryTerm = {
|
||||||
name,
|
name,
|
||||||
displayName: name,
|
displayName: name,
|
||||||
@ -382,6 +407,9 @@ const AddGlossaryTerm = ({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
{showErrorMsg.invalidReferences
|
||||||
|
? errorMsg('Endpoints should be valid URL.')
|
||||||
|
: null}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Field>
|
<Field>
|
||||||
|
@ -75,7 +75,7 @@ const GlossaryReferences: FunctionComponent<Props> = ({
|
|||||||
<input
|
<input
|
||||||
className="tw-form-inputs tw-px-3 tw-py-1"
|
className="tw-form-inputs tw-px-3 tw-py-1"
|
||||||
id={`name-${i}`}
|
id={`name-${i}`}
|
||||||
name="key"
|
name="name"
|
||||||
placeholder="Name"
|
placeholder="Name"
|
||||||
type="text"
|
type="text"
|
||||||
value={value.name}
|
value={value.name}
|
||||||
@ -89,7 +89,7 @@ const GlossaryReferences: FunctionComponent<Props> = ({
|
|||||||
className="tw-form-inputs tw-px-3 tw-py-1"
|
className="tw-form-inputs tw-px-3 tw-py-1"
|
||||||
id={`url-${i}`}
|
id={`url-${i}`}
|
||||||
name="endpoint"
|
name="endpoint"
|
||||||
placeholder="url"
|
placeholder="Endpoint"
|
||||||
type="text"
|
type="text"
|
||||||
value={value.endpoint}
|
value={value.endpoint}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { cloneDeep, includes, isEqual } from 'lodash';
|
import { cloneDeep, includes, isEqual } from 'lodash';
|
||||||
import { EntityTags, FormatedUsersData, GlossaryTermAssets } from 'Models';
|
import { EntityTags, FormatedUsersData, GlossaryTermAssets } from 'Models';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { Fragment, useEffect, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
LIST_SIZE,
|
LIST_SIZE,
|
||||||
TITLE_FOR_NON_ADMIN_ACTION,
|
TITLE_FOR_NON_ADMIN_ACTION,
|
||||||
@ -102,7 +102,12 @@ const GlossaryTermsV1 = ({
|
|||||||
const oldReviewer = data.filter((d) => includes(reviewer, d));
|
const oldReviewer = data.filter((d) => includes(reviewer, d));
|
||||||
const newReviewer = data
|
const newReviewer = data
|
||||||
.filter((d) => !includes(reviewer, d))
|
.filter((d) => !includes(reviewer, d))
|
||||||
.map((d) => ({ id: d.id, type: d.type }));
|
.map((d) => ({
|
||||||
|
id: d.id,
|
||||||
|
type: d.type,
|
||||||
|
displayName: d.displayName,
|
||||||
|
name: d.name,
|
||||||
|
}));
|
||||||
updatedGlossaryTerm = {
|
updatedGlossaryTerm = {
|
||||||
...updatedGlossaryTerm,
|
...updatedGlossaryTerm,
|
||||||
reviewers: [...oldReviewer, ...newReviewer],
|
reviewers: [...oldReviewer, ...newReviewer],
|
||||||
@ -384,36 +389,32 @@ const GlossaryTermsV1 = ({
|
|||||||
{references && references.length ? (
|
{references && references.length ? (
|
||||||
<div className="tw-flex">
|
<div className="tw-flex">
|
||||||
{references.map((d, i) => (
|
{references.map((d, i) => (
|
||||||
<>
|
<Fragment key={i}>
|
||||||
{i > 0 && <span className="tw-mr-2">,</span>}
|
{i > 0 && <span className="tw-mr-2">,</span>}
|
||||||
<a
|
<a
|
||||||
className="link-text tw-flex"
|
className="link-text tw-flex"
|
||||||
data-testid="owner-link"
|
data-testid="owner-link"
|
||||||
href={d?.endpoint}
|
href={d?.endpoint}
|
||||||
key={i}
|
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<>
|
<span
|
||||||
<span
|
className={classNames(
|
||||||
className={classNames(
|
'tw-mr-1 tw-inline-block tw-truncate',
|
||||||
'tw-mr-1 tw-inline-block tw-truncate',
|
{
|
||||||
{
|
'tw-w-52': (d?.name as string).length > 32,
|
||||||
'tw-w-52': (d?.name as string).length > 32,
|
}
|
||||||
}
|
)}
|
||||||
)}
|
title={d?.name as string}>
|
||||||
title={d?.name as string}>
|
{d?.name}
|
||||||
{d?.name}
|
</span>
|
||||||
</span>
|
<SVGIcons
|
||||||
|
alt="external-link"
|
||||||
<SVGIcons
|
className="tw-align-middle"
|
||||||
alt="external-link"
|
icon="external-link"
|
||||||
className="tw-align-middle"
|
width="12px"
|
||||||
icon="external-link"
|
/>
|
||||||
width="12px"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
</a>
|
</a>
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
@ -11,8 +11,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { TermReference } from '../../../generated/entity/data/glossaryTerm';
|
import { TermReference } from '../../../generated/entity/data/glossaryTerm';
|
||||||
|
import { errorMsg, isValidUrl } from '../../../utils/CommonUtils';
|
||||||
import { Button } from '../../buttons/Button/Button';
|
import { Button } from '../../buttons/Button/Button';
|
||||||
import GlossaryReferences from '../../GlossaryReferences/GlossaryReferences';
|
import GlossaryReferences from '../../GlossaryReferences/GlossaryReferences';
|
||||||
|
|
||||||
@ -30,11 +32,40 @@ const GlossaryReferenceModal = ({
|
|||||||
header,
|
header,
|
||||||
}: RelatedTermsModalProp) => {
|
}: RelatedTermsModalProp) => {
|
||||||
const [references, setReferences] = useState<TermReference[]>(
|
const [references, setReferences] = useState<TermReference[]>(
|
||||||
referenceList || []
|
cloneDeep(referenceList) || []
|
||||||
);
|
);
|
||||||
|
const [errMsg, setErrMsg] = useState<string>();
|
||||||
|
|
||||||
const handleReferenceFieldChange = (refs: TermReference[]) => {
|
const handleReferenceFieldChange = (refs: TermReference[]) => {
|
||||||
setReferences(refs);
|
setReferences(refs);
|
||||||
|
setErrMsg('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const isValid = (refs: TermReference[]): boolean => {
|
||||||
|
let retVal = true;
|
||||||
|
for (const ref of refs) {
|
||||||
|
if (!isValidUrl(ref.endpoint || '')) {
|
||||||
|
retVal = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
const refList = references
|
||||||
|
.map((item) => ({
|
||||||
|
name: item.name?.trim(),
|
||||||
|
endpoint: item.endpoint?.trim(),
|
||||||
|
}))
|
||||||
|
.filter((item) => item.name && item.endpoint);
|
||||||
|
if (isValid(refList)) {
|
||||||
|
onSave(references);
|
||||||
|
} else {
|
||||||
|
setErrMsg('Endpoints should be valid URL.');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -51,6 +82,7 @@ const GlossaryReferenceModal = ({
|
|||||||
referenceList={references}
|
referenceList={references}
|
||||||
onReferenceFieldChange={handleReferenceFieldChange}
|
onReferenceFieldChange={handleReferenceFieldChange}
|
||||||
/>
|
/>
|
||||||
|
{errMsg && errorMsg(errMsg)}
|
||||||
</div>
|
</div>
|
||||||
<div className="tw-modal-footer" data-testid="cta-container">
|
<div className="tw-modal-footer" data-testid="cta-container">
|
||||||
<Button
|
<Button
|
||||||
@ -66,7 +98,7 @@ const GlossaryReferenceModal = ({
|
|||||||
theme="primary"
|
theme="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={() => onSave(references)}>
|
onClick={handleSave}>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -341,14 +341,14 @@ export const navLinkDevelop = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const navLinkSettings = [
|
export const navLinkSettings = [
|
||||||
{ name: 'Teams', to: '/teams', disabled: false },
|
|
||||||
{ name: 'Roles', to: '/roles', disabled: false, isAdminOnly: true },
|
|
||||||
{ name: 'Users', to: '/user-list', disabled: false, isAdminOnly: true },
|
|
||||||
{ name: 'Tags', to: '/tags', disabled: false },
|
|
||||||
// { name: 'Store', to: '/store', disabled: false },
|
|
||||||
{ name: 'Services', to: '/services', disabled: false },
|
|
||||||
{ name: 'Webhooks', to: '/webhooks', disabled: false },
|
|
||||||
{ name: 'Glossaries', to: '/glossary', disabled: false },
|
{ name: 'Glossaries', to: '/glossary', disabled: false },
|
||||||
|
{ name: 'Roles', to: '/roles', disabled: false, isAdminOnly: true },
|
||||||
|
{ name: 'Services', to: '/services', disabled: false },
|
||||||
|
{ name: 'Tags', to: '/tags', disabled: false },
|
||||||
|
{ name: 'Teams', to: '/teams', disabled: false },
|
||||||
|
{ name: 'Users', to: '/user-list', disabled: false, isAdminOnly: true },
|
||||||
|
// { name: 'Store', to: '/store', disabled: false },
|
||||||
|
{ name: 'Webhooks', to: '/webhooks', disabled: false },
|
||||||
// { name: 'Ingestions', to: '/ingestion', disabled: false },
|
// { name: 'Ingestions', to: '/ingestion', disabled: false },
|
||||||
// { name: 'Marketplace', to: '/marketplace', disabled: true },
|
// { name: 'Marketplace', to: '/marketplace', disabled: true },
|
||||||
// { name: 'Preferences', to: '/preference', disabled: true },
|
// { name: 'Preferences', to: '/preference', disabled: true },
|
||||||
|
@ -322,7 +322,32 @@ const GlossaryPageV1 = () => {
|
|||||||
const updateGlossary = (updatedData: Glossary) => {
|
const updateGlossary = (updatedData: Glossary) => {
|
||||||
saveUpdatedGlossaryData(updatedData)
|
saveUpdatedGlossaryData(updatedData)
|
||||||
.then((res: AxiosResponse) => {
|
.then((res: AxiosResponse) => {
|
||||||
setSelectedData(res.data);
|
if (res?.data) {
|
||||||
|
const { data } = res;
|
||||||
|
setSelectedData(data);
|
||||||
|
setGlossaries((pre) => {
|
||||||
|
return pre.map((item) => {
|
||||||
|
if (item.name === data.name) {
|
||||||
|
const { children } = item;
|
||||||
|
|
||||||
|
return extend(cloneDeep(item), { ...data, children });
|
||||||
|
} else {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setGlossariesList((pre) => {
|
||||||
|
return pre.map((item) => {
|
||||||
|
if (item.name === data.name) {
|
||||||
|
const { children } = item;
|
||||||
|
|
||||||
|
return extend(cloneDeep(item), { ...data, children });
|
||||||
|
} else {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err: AxiosError) => {
|
.catch((err: AxiosError) => {
|
||||||
showToast({
|
showToast({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user