/** * Copyright (c) 2020-present, Goldman Sachs * * 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 { prettyCONSTName } from '@finos/legend-shared'; import { UMLEditorState, UML_EDITOR_TAB, } from '../../../../stores/editor/editor-state/element-editor-state/UMLEditorState.js'; import { observer } from 'mobx-react-lite'; import { clsx, InputWithInlineValidation, PlusIcon, TimesIcon, LockIcon, PanelEntryDragHandle, DragPreviewLayer, useDragPreviewLayer, Panel, PanelContent, PanelDnDEntry, PanelContentLists, } from '@finos/legend-art'; import { LEGEND_STUDIO_TEST_ID } from '../../../../__lib__/LegendStudioTesting.js'; import { useEditorStore } from '../../EditorStoreProvider.js'; import { type Profile, type Stereotype, stub_Tag, stub_Stereotype, type Tag, } from '@finos/legend-graph'; import { profile_addTag, profile_addStereotype, profile_deleteTag, profile_deleteStereotype, tagStereotype_setValue, profile_swapTags, profile_swapStereotypes, } from '../../../../stores/graph-modifier/DomainGraphModifierHelper.js'; import { useApplicationNavigationContext } from '@finos/legend-application'; import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js'; import { useRef, useCallback } from 'react'; import { useDrop, useDrag } from 'react-dnd'; type TagDragSource = { tag: Tag; }; const TAG_DND_TYPE = 'TAG'; const TagBasicEditor = observer( (props: { tag: Tag; deleteValue: () => void; _profile: Profile; isReadOnly: boolean; }) => { const ref = useRef(null); const handleRef = useRef(null); const { tag, _profile, deleteValue, isReadOnly } = props; const changeValue: React.ChangeEventHandler = (event) => { tagStereotype_setValue(tag, event.target.value); }; const isTagDuplicated = (val: Tag): boolean => tag._OWNER.p_tags.filter((t) => t.value === val.value).length >= 2; // Drag and Drop const handleHover = useCallback( (item: TagDragSource): void => { const draggingTag = item.tag; const hoveredTag = tag; profile_swapTags(_profile, draggingTag, hoveredTag); }, [_profile, tag], ); const [{ isBeingDraggedTag }, dropConnector] = useDrop< TagDragSource, void, { isBeingDraggedTag: Tag | undefined } >( () => ({ accept: [TAG_DND_TYPE], hover: (item) => handleHover(item), collect: (monitor) => ({ isBeingDraggedTag: monitor.getItem()?.tag, }), }), [handleHover], ); const isBeingDragged = tag === isBeingDraggedTag; const [, dragConnector, dragPreviewConnector] = useDrag( () => ({ type: TAG_DND_TYPE, item: () => ({ tag: tag, }), }), [tag], ); dragConnector(handleRef); dropConnector(ref); useDragPreviewLayer(dragPreviewConnector); return ( } showPlaceholder={isBeingDragged} >
{!isReadOnly && ( )}
); }, ); type StereotypeDragSource = { stereotype: Stereotype; }; const STEREOTYPE_DND_TYPE = 'STEREOTYPE'; const StereotypeBasicEditor = observer( (props: { stereotype: Stereotype; deleteStereotype: () => void; _profile: Profile; isReadOnly: boolean; }) => { const ref = useRef(null); const handleRef = useRef(null); const { stereotype, _profile, deleteStereotype, isReadOnly } = props; const changeValue: React.ChangeEventHandler = (event) => { tagStereotype_setValue(stereotype, event.target.value); }; const isStereotypeDuplicated = (val: Stereotype): boolean => stereotype._OWNER.p_stereotypes.filter((s) => s.value === val.value) .length >= 2; // Drag and Drop const handleHover = useCallback( (item: StereotypeDragSource): void => { const draggingTag = item.stereotype; const hoveredTag = stereotype; profile_swapStereotypes(_profile, draggingTag, hoveredTag); }, [_profile, stereotype], ); const [{ isBeingDraggedTag }, dropConnector] = useDrop< StereotypeDragSource, void, { isBeingDraggedTag: Tag | undefined } >( () => ({ accept: [STEREOTYPE_DND_TYPE], hover: (item) => handleHover(item), collect: (monitor) => ({ isBeingDraggedTag: monitor.getItem() ?.stereotype, }), }), [handleHover], ); const isBeingDragged = stereotype === isBeingDraggedTag; const [, dragConnector, dragPreviewConnector] = useDrag( () => ({ type: STEREOTYPE_DND_TYPE, item: () => ({ stereotype: stereotype, }), }), [stereotype], ); dragConnector(handleRef); dropConnector(ref); useDragPreviewLayer(dragPreviewConnector); return ( } className="stereotype-basic-editor__container" showPlaceholder={isBeingDragged} >
{!isReadOnly && ( )}
); }, ); export const ProfileEditor = observer((props: { profile: Profile }) => { const { profile } = props; const editorStore = useEditorStore(); const editorState = editorStore.tabManagerState.getCurrentEditorState(UMLEditorState); const isReadOnly = editorState.isReadOnly; // Tab const selectedTab = editorState.selectedTab; const tabs = [UML_EDITOR_TAB.TAGS, UML_EDITOR_TAB.STEREOTYPES]; const changeTab = (tab: UML_EDITOR_TAB): (() => void) => (): void => editorState.setSelectedTab(tab); // Tagged value and Stereotype let addButtonTitle = ''; switch (selectedTab) { case UML_EDITOR_TAB.TAGS: addButtonTitle = 'Add tagged value'; break; case UML_EDITOR_TAB.STEREOTYPES: addButtonTitle = 'Add stereotype'; break; default: break; } const addValue = (): void => { if (!isReadOnly) { if (selectedTab === UML_EDITOR_TAB.TAGS) { profile_addTag(profile, stub_Tag(profile)); } else if (selectedTab === UML_EDITOR_TAB.STEREOTYPES) { profile_addStereotype(profile, stub_Stereotype(profile)); } } }; const deleteStereotype = (val: Stereotype): (() => void) => (): void => profile_deleteStereotype(profile, val); const deleteTag = (val: Tag): (() => void) => (): void => profile_deleteTag(profile, val); useApplicationNavigationContext( LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.PROFILE_EDITOR, ); return (
{isReadOnly && (
)}
profile
{profile.name}
{tabs.map((tab) => (
{prettyCONSTName(tab)}
))}
{selectedTab === UML_EDITOR_TAB.TAGS && ( item.tag.value === '' ? '(unknown)' : item.tag.value } types={[TAG_DND_TYPE]} /> {profile.p_tags.map((tag) => ( ))} )} {selectedTab === UML_EDITOR_TAB.STEREOTYPES && ( item.stereotype.value === '' ? '(unknown)' : item.stereotype.value } types={[STEREOTYPE_DND_TYPE]} /> {profile.p_stereotypes.map((stereotype) => ( ))} )}
); });