Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(designer): Title changes not updating downstream inputs when serializing #4407

Merged
merged 10 commits into from
Mar 21, 2024
2 changes: 1 addition & 1 deletion __mocks__/workflows/Panel.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"Filter_array": {
"type": "Query",
"inputs": {
"from": "@triggerBody()?['array']",
"from": "@body('Parse_JSON')",
"where": "@not(contains(length(split(item(), '|')?[0]),length(split(item(), '|')?[0])))"
},
"runAfter": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export const CollapsedAuthentication = ({
editorState.read(() => {
const nodeMap = new Map<string, ValueSegment>();
const editorString = getChildrenNodes($getRoot(), nodeMap).trim();
console.log(editorString);
const newCollapsedValue = serializeEditorState(editorState);
try {
// no collapsed value, update current Props to be empty
Expand Down
8 changes: 0 additions & 8 deletions libs/designer-ui/src/lib/code/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,6 @@ export function CodeEditor({
setInTokenPicker(!getInTokenPicker());
};

const setIsInTokenpicker = (b: boolean) => {
setInTokenPicker(b);
if (!b) {
codeEditorRef.current?.focus();
}
};

const tokenClicked = (valueSegment: ValueSegment) => {
if (codeEditorRef.current && valueSegment.token) {
const newText = buildInlineCodeTextFromToken(valueSegment.token, language);
Expand Down Expand Up @@ -122,7 +115,6 @@ export function CodeEditor({
callOutLabelId,
undefined /* TokenPickerMode: undefined uses legacy tokenpicker */,
undefined /* Editortype: undefined defaults to parameter type */,
setIsInTokenpicker,
tokenClicked
)
: null}
Expand Down
5 changes: 2 additions & 3 deletions libs/designer-ui/src/lib/editor/base/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export type GetTokenPickerHandler = (
labelId: string,
tokenPickerMode?: TokenPickerMode,
valueType?: string,
setInTokenpicker?: (b: boolean) => void,
tokenClickedCallback?: (token: ValueSegment) => void
) => JSX.Element;

Expand Down Expand Up @@ -216,7 +215,7 @@ export const BaseEditor = ({
{htmlEditor === 'rich-html' ? null : <ArrowNavigation />}
{tokens ? (
<>
<InsertTokenNode closeTokenPicker={() => setIsTokenPickerOpened(false)} />
<InsertTokenNode />
<DeleteTokenNode />
<OpenTokenPicker openTokenPicker={openTokenPicker} />
<CloseTokenPicker closeTokenPicker={() => setIsTokenPickerOpened(false)} />
Expand All @@ -232,7 +231,7 @@ export const BaseEditor = ({
<FloatingLinkEditorPlugin anchorElem={floatingAnchorElem} isMainEditorFocused={isEditorFocused} />
) : null}
{children}
{tokens && isTokenPickerOpened ? getTokenPicker(editorId, labelId ?? '', tokenPickerMode, valueType, setIsTokenPickerOpened) : null}
{tokens && isTokenPickerOpened ? getTokenPicker(editorId, labelId ?? '', tokenPickerMode, valueType) : null}
</div>
{tokens && isEditorFocused && !isTokenPickerOpened
? createPortal(<TokenPickerButton {...tokenPickerButtonProps} openTokenPicker={openTokenPicker} />, document.body)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import type { LexicalCommand } from 'lexical';
import { COMMAND_PRIORITY_EDITOR, createCommand } from 'lexical';
import { useEffect } from 'react';

export const CLOSE_TOKENPICKER: LexicalCommand<undefined> = createCommand();
interface CloseTokenPickerPaylaod {
focusEditorAfter?: boolean;
}
export const CLOSE_TOKENPICKER: LexicalCommand<CloseTokenPickerPaylaod> = createCommand();

export interface CloseTokenPickerProps {
closeTokenPicker: () => void;
Expand All @@ -15,8 +18,11 @@ export default function CloseTokenPicker({ closeTokenPicker }: CloseTokenPickerP
useEffect(() => {
return editor.registerCommand(
CLOSE_TOKENPICKER,
() => {
(payload) => {
closeTokenPicker();
if (payload.focusEditorAfter) {
editor.focus();
}
return true;
},
COMMAND_PRIORITY_EDITOR
Expand Down
11 changes: 4 additions & 7 deletions libs/designer-ui/src/lib/editor/base/plugins/InsertTokenNode.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import type { TokenNodeProps } from '../nodes/tokenNode';
import { $createTokenNode, TokenNode } from '../nodes/tokenNode';
import { CLOSE_TOKENPICKER } from './CloseTokenPicker';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import type { LexicalCommand } from 'lexical';
import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_EDITOR, createCommand } from 'lexical';
import { useEffect } from 'react';

export const INSERT_TOKEN_NODE: LexicalCommand<TokenNodeProps> = createCommand();

export interface InsertTokenNodeProps {
closeTokenPicker: () => void;
}

export default function InsertTokenNode({ closeTokenPicker }: InsertTokenNodeProps): null {
export default function InsertTokenNode(): null {
const [editor] = useLexicalComposerContext();

useEffect(() => {
Expand All @@ -28,12 +25,12 @@ export default function InsertTokenNode({ closeTokenPicker }: InsertTokenNodePro
const tokenNode = $createTokenNode({ ...payload, value, readonly: false });
selection.insertNodes([tokenNode]);
}
closeTokenPicker();
editor.dispatchCommand(CLOSE_TOKENPICKER, { focusEditorAfter: true });
return true;
},
COMMAND_PRIORITY_EDITOR
);
}, [editor, closeTokenPicker]);
}, [editor]);

return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ export interface PanelHeaderTitleProps {

export const PanelHeaderTitle = ({
titleValue,
onChange,
titleId,
readOnlyMode,
renameTitleDisabled,
onChange,
}: PanelHeaderTitleProps): JSX.Element => {
const intl = useIntl();

Expand Down
7 changes: 3 additions & 4 deletions libs/designer-ui/src/lib/token/inputToken.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const InputToken: React.FC<InputTokenProps> = ({ value, brandColor, icon,
} else {
clearSelection();
setSelected(true);
editor.dispatchCommand(CLOSE_TOKENPICKER, undefined);
editor.dispatchCommand(CLOSE_TOKENPICKER, { focusEditorAfter: true });
}
});
}
Expand Down Expand Up @@ -130,12 +130,11 @@ export const InputToken: React.FC<InputTokenProps> = ({ value, brandColor, icon,
handleTokenClicked(e);
e.stopPropagation();
}}
title={value}
style={tokenStyle}
ref={tokenRef}
>
<div className="msla-token-title" title={value}>
{title}
</div>
<div className="msla-token-title">{title}</div>
{renderTokenDeleteButton()}
</span>
);
Expand Down
170 changes: 80 additions & 90 deletions libs/designer-ui/src/lib/tokenpicker/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ValueSegment } from '../editor';
import { CLOSE_TOKENPICKER } from '../editor/base/plugins/CloseTokenPicker';
import type { ExpressionEditorEvent } from '../expressioneditor';
import { ExpressionEditor } from '../expressioneditor';
import { PanelSize } from '../panel/panelUtil';
Expand All @@ -11,7 +12,7 @@ import { TokenPickerPivot } from './tokenpickerpivot';
import type { GetValueSegmentHandler } from './tokenpickersection/tokenpickeroption';
import { TokenPickerSection } from './tokenpickersection/tokenpickersection';
import type { ICalloutContentStyles, ISearchBox, PivotItem } from '@fluentui/react';
import { SearchBox, Callout, DirectionalHint, FocusTrapZone } from '@fluentui/react';
import { SearchBox, DirectionalHint, Callout } from '@fluentui/react';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import type { LexicalEditor, NodeKey } from 'lexical';
import type { editor } from 'monaco-editor';
Expand Down Expand Up @@ -48,7 +49,6 @@ export interface TokenPickerProps {
expressionGroup?: TokenGroup[];
// if initialMode is undefined, it is Legacy TokenPicker
initialMode?: TokenPickerMode;
setIsTokenPickerOpened?: (b: boolean) => void;
// tokenClickedCallback is used for the code Editor TokenPicker(Legacy Token Picker)
tokenClickedCallback?: (token: ValueSegment) => void;
hideUTFExpressions?: boolean;
Expand All @@ -61,13 +61,11 @@ export function TokenPicker({
expressionGroup,
initialMode,
hideUTFExpressions,
setIsTokenPickerOpened,
getValueSegmentFromToken,
tokenClickedCallback,
}: TokenPickerProps): JSX.Element {
const intl = useIntl();
const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
const [isTokenPickerVisible, setIsTokenPickerVisible] = useState(true);
const [searchQuery, setSearchQuery] = useState('');
const [selectedKey, setSelectedKey] = useState<TokenPickerMode>(initialMode ?? TokenPickerMode.TOKEN);
const [expressionToBeUpdated, setExpressionToBeUpdated] = useState<NodeKey | null>(null);
Expand All @@ -77,6 +75,7 @@ export function TokenPicker({
const [expressionEditorDragDistance, setExpressionEditorDragDistance] = useState(0);
const [expressionEditorCurrentHeight, setExpressionEditorCurrentHeight] = useState(windowDimensions.height < 400 ? 50 : 100);
const [expressionEditorError, setExpressionEditorError] = useState<string>('');
const containerRef = useRef<HTMLDivElement | null>(null);
const expressionEditorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
const searchBoxRef = useRef<ISearchBox | null>(null);
const isExpression = initialMode === TokenPickerMode.EXPRESSION;
Expand Down Expand Up @@ -161,10 +160,6 @@ export function TokenPicker({
editor = null;
}

const closeTokenPicker = () => {
setIsTokenPickerOpened?.(false);
};

return (
<>
<Callout
Expand All @@ -181,12 +176,11 @@ export function TokenPicker({
}
}}
onDismiss={(e) => {
setIsTokenPickerVisible(false);
if (e?.type === 'keydown' && (e as React.KeyboardEvent<HTMLElement>).key === 'Escape') {
editor?.focus();
editor?.dispatchCommand(CLOSE_TOKENPICKER, { focusEditorAfter: true });
} else {
editor?.dispatchCommand(CLOSE_TOKENPICKER, { focusEditorAfter: false });
}

closeTokenPicker();
}}
onRestoreFocus={() => {
return;
Expand All @@ -196,91 +190,87 @@ export function TokenPicker({
hostId: 'msla-layer-host',
}}
>
<FocusTrapZone isClickableOutsideFocusTrap disabled={!isTokenPickerVisible}>
<div
className="msla-token-picker-container-v3"
style={
fullScreen
? {
height: Math.max(windowDimensions.height - 100, Math.min(windowDimensions.height, 550)),
width: Math.max(
windowDimensions.width - (parseInt(PanelSize.Medium, 10) + 40),
Math.min(windowDimensions.width - 16, 400)
),
}
: { maxHeight: Math.min(windowDimensions.height, 550), width: Math.min(windowDimensions.width - 16, 400) }
}
>
<div className="msla-token-picker">
{initialMode ? (
<TokenPickerHeader
fullScreen={fullScreen}
isExpression={isExpression}
closeTokenPicker={closeTokenPicker}
setFullScreen={setFullScreen}
pasteLastUsedExpression={pasteLastUsedExpression}
/>
) : null}
<div
className="msla-token-picker-container-v3"
style={
fullScreen
? {
height: Math.max(windowDimensions.height - 100, Math.min(windowDimensions.height, 550)),
width: Math.max(
windowDimensions.width - (parseInt(PanelSize.Medium, 10) + 40),
Math.min(windowDimensions.width - 16, 400)
),
}
: { maxHeight: Math.min(windowDimensions.height, 550), width: Math.min(windowDimensions.width - 16, 400) }
}
ref={containerRef}
>
<div className="msla-token-picker">
{initialMode ? (
<TokenPickerHeader
fullScreen={fullScreen}
isExpression={isExpression}
setFullScreen={setFullScreen}
pasteLastUsedExpression={pasteLastUsedExpression}
/>
) : null}

{isExpression ? (
<div className="msla-token-picker-expression-subheader">
<ExpressionEditor
initialValue={expression.value}
editorRef={expressionEditorRef}
onBlur={onExpressionEditorBlur}
isDragging={isDraggingExpressionEditor}
dragDistance={expressionEditorDragDistance}
setIsDragging={setIsDraggingExpressionEditor}
currentHeight={expressionEditorCurrentHeight}
setCurrentHeight={setExpressionEditorCurrentHeight}
setExpressionEditorError={setExpressionEditorError}
hideUTFExpressions={hideUTFExpressions}
/>
<div className="msla-token-picker-expression-editor-error">{expressionEditorError}</div>
<TokenPickerPivot selectedKey={selectedKey} selectKey={handleSelectKey} hideExpressions={!!tokenClickedCallback} />
</div>
) : null}
<div className="msla-token-picker-search-container">
<SearchBox
className="msla-token-picker-search"
componentRef={(e) => {
searchBoxRef.current = e;
}}
placeholder={tokenPickerPlaceHolderText}
onChange={(_, newValue) => {
setSearchQuery(newValue ?? '');
}}
data-automation-id="msla-token-picker-search"
{isExpression ? (
<div className="msla-token-picker-expression-subheader">
<ExpressionEditor
initialValue={expression.value}
editorRef={expressionEditorRef}
onBlur={onExpressionEditorBlur}
isDragging={isDraggingExpressionEditor}
dragDistance={expressionEditorDragDistance}
setIsDragging={setIsDraggingExpressionEditor}
currentHeight={expressionEditorCurrentHeight}
setCurrentHeight={setExpressionEditorCurrentHeight}
setExpressionEditorError={setExpressionEditorError}
hideUTFExpressions={hideUTFExpressions}
/>
<div className="msla-token-picker-expression-editor-error">{expressionEditorError}</div>
<TokenPickerPivot selectedKey={selectedKey} selectKey={handleSelectKey} hideExpressions={!!tokenClickedCallback} />
</div>
<TokenPickerSection
tokenGroup={(selectedKey === TokenPickerMode.TOKEN ? filteredTokenGroup : tokenGroup) ?? []}
expressionGroup={expressionGroup ?? []}
expressionEditorRef={expressionEditorRef}
selectedKey={selectedKey}
searchQuery={searchQuery}
fullScreen={fullScreen}
) : null}
<div className="msla-token-picker-search-container">
<SearchBox
className="msla-token-picker-search"
componentRef={(e) => {
searchBoxRef.current = e;
}}
placeholder={tokenPickerPlaceHolderText}
onChange={(_, newValue) => {
setSearchQuery(newValue ?? '');
}}
data-automation-id="msla-token-picker-search"
/>
</div>
<TokenPickerSection
tokenGroup={(selectedKey === TokenPickerMode.TOKEN ? filteredTokenGroup : tokenGroup) ?? []}
expressionGroup={expressionGroup ?? []}
expressionEditorRef={expressionEditorRef}
selectedKey={selectedKey}
searchQuery={searchQuery}
fullScreen={fullScreen}
expression={expression}
setExpression={setExpression}
getValueSegmentFromToken={getValueSegmentFromToken}
tokenClickedCallback={tokenClickedCallback}
noDynamicContent={!isDynamicContentAvailable(filteredTokenGroup ?? [])}
expressionEditorCurrentHeight={expressionEditorCurrentHeight}
/>
{isExpression ? (
<TokenPickerFooter
tokenGroup={tokenGroup ?? []}
expression={expression}
setExpression={setExpression}
expressionToBeUpdated={expressionToBeUpdated}
getValueSegmentFromToken={getValueSegmentFromToken}
tokenClickedCallback={tokenClickedCallback}
noDynamicContent={!isDynamicContentAvailable(filteredTokenGroup ?? [])}
closeTokenPicker={closeTokenPicker}
expressionEditorCurrentHeight={expressionEditorCurrentHeight}
setExpressionEditorError={setExpressionEditorError}
/>
{isExpression ? (
<TokenPickerFooter
tokenGroup={tokenGroup ?? []}
expression={expression}
expressionToBeUpdated={expressionToBeUpdated}
getValueSegmentFromToken={getValueSegmentFromToken}
setExpressionEditorError={setExpressionEditorError}
closeTokenPicker={closeTokenPicker}
/>
) : null}
</div>
) : null}
</div>
</FocusTrapZone>
</div>
</Callout>
{tokenClickedCallback ? null : <TokenPickerHandler handleUpdateExpressionToken={handleUpdateExpressionToken} />}
{tokenClickedCallback ? null : <UpdateTokenNode />}
Expand Down
Loading
Loading